2016-05-12 188 views
0

我想使用AutoMapper的ProjectTo擴展方法將基於實體框架表的對象轉換爲自定義的DTO。在EF對面的人實體看起來是這樣的:AutoMapper.ProjectTo與字段級別類型轉換

public partial class Person 
{ 
    public int PersonId { get; set; } 
    public string Name { get; set; } 
    public string Age { get; set; } 
} 

的PersonViewModel,我投射到看起來像這樣DTO:

public class PersonViewModel 
{ 
    public PersonViewModel(Person p) 
    { 
     PersonId = p.PersonId; 
     Name = p.Name; 
     Age = Convert.ToInt32(p.Age); 
    } 

    public PersonViewModel() 
    { 

    } 

    public PersonViewModel(int id, string name, int age) 
    { 
     PersonId = id; 
     Name = name; 
     Age = age; 
    } 

    public int PersonId { get; set; } 
    public string Name { get; set; } 
    public int Age { get; set; } 
} 

要注意的關鍵一點是,人表中包含的字段稱爲Age的nvarchar類型,PersonViewModel具有Age類型的int類型。不幸的是,我無法更改表格,而必須找到轉換數據的方法。

以下代碼是我嘗試過的AutoMapper配置,它們的「問題」以及使用代碼(數據庫調用等)。

MapperConfiguration config = new MapperConfiguration(cfg => 
     { 
      // ----- Throws "Unable to create map expression" exception ------ 
      //cfg.CreateMap<Person, PersonViewModel>(); 


      // ----- Throws "Linq to Entities does not support method" exception ------ 
      //cfg.CreateMap<Person, PersonViewModel>() 
      // .ForMember(dest => dest.Age, opt => opt.MapFrom(src => Convert.ToInt32(src.Age))); 


      // ----- Throws "Unable to create map expression" exception ------ 
      //cfg.CreateMap<Person, PersonViewModel>() 
      // .ConstructProjectionUsing(src => new PersonViewModel 
      // { 
      //  PersonId = src.PersonId, 
      //  Name = src.Name, 
      //  Age = Convert.ToInt32(src.Age) 
      // }); 


      // ----- Throws "Unable to create map expression" exception ------ 
      //cfg.CreateMap<Person, PersonViewModel>() 
      // .ConstructProjectionUsing(src => new PersonViewModel(src.PersonId, src.Name, Convert.ToInt32(src.Age))); 


      // ----- Throws "Unable to create map expression" exception ------ 
      //cfg.CreateMap<Person, PersonViewModel>() 
      // .ConstructProjectionUsing(src => new PersonViewModel(src.PersonId, src.Name, 25)); 


      // ----- Throws "Linq to Entities does not support method" exception ------ 
      //cfg.CreateMap<Person, PersonViewModel>() 
      // .ProjectUsing(src => new PersonViewModel 
      // { 
      //  PersonId = src.PersonId, 
      //  Name = src.Name, 
      //  Age = Convert.ToInt32(src.Age) 
      // }); 


      // ----- Throws "Unable to create map expression" exception ------ 
      //cfg.CreateMap<Person, PersonViewModel>() 
      // .ConstructUsing(src => new PersonViewModel 
      // { 
      //  PersonId = src.PersonId, 
      //  Name = src.Name, 
      //  Age = Convert.ToInt32(src.Age) 
      // }); 


      // ----- Throws "Unable to create map expression" exception ------ 
      //cfg.CreateMap<Person, PersonViewModel>() 
      // .ConstructUsing(src => new PersonViewModel(src)); 


      // ----- Doesn't throw exception, but all values are null or 0. ------ 
      //cfg.CreateMap<Person, PersonViewModel>() 
      // .ConvertUsing(src => new PersonViewModel 
      // { 
      //  PersonId = src.PersonId, 
      //  Name = src.Name, 
      //  Age = Convert.ToInt32(src.Age) 
      // }); 


      // ----- Doesn't throw exception, but all values are null or 0. ------ 
      //cfg.CreateMap<Person, PersonViewModel>() 
      // .ConvertUsing(src => new PersonViewModel(src.PersonId, src.Name, Convert.ToInt32(src.Age))); 


      // ----- Works, but bypasses the conversion I need ------ 
      //cfg.CreateMap<Person, PersonViewModel>() 
      // .ProjectUsing(src => new PersonViewModel 
      // { 
      //  PersonId = src.PersonId, 
      //  Name = src.Name, 
      //  Age = 25 
      // }); 


      // ----- Works, but bypasses the conversion I need ------ 
      cfg.CreateMap<Person, PersonViewModel>() 
       .ForMember(dest => dest.Age, opt => opt.MapFrom(src => 35)); 
     }); 

     using (FamilyEntities db = new FamilyEntities()) 
     { 
      PersonViewModel p = db.Set<Person>() 
       .Where(x => x.PersonId == 1) 
       .ProjectTo<PersonViewModel>(config) 
       .SingleOrDefault(); 

      Console.WriteLine("Name: " + p.Name + Environment.NewLine + "Age: " + p.Age); 
     } 

     Console.ReadLine(); 

是否可以使用AutoMapper的ProjectTo將字符串轉換爲int?其次,如果可能的話,那個配置是​​什麼樣的?

在此先感謝您的幫助。

+0

http://stackoverflow.com/a/24027242/1736944可能會爲您提供一個可行的解決方法,除非automapper有一些聰明的東西。 – 9Rune5

+0

@ 9Rune5 - 感謝您指出EF的可擴展性。我不知道你可以像這樣定義你自己的方法。我測試了這一點,這是一個可行的解決方法。如果你提供這個答案,我會接受它。 – user1011627

回答

2

你的第一個嘗試是爲什麼這不起作用。實體框架不知道如何將一個字符串轉換爲一個整型,所以你被弄糊塗了。其他方面都不重要,重要的是EF給你的例外。

如果EF無法支持轉換,AutoMapper無法爲您提供幫助。

相反,我會做類似轉換您的視圖模型的內部:

public class PersonViewModel 
{ 
    public int PersonId { get; set; } 
    public string Name { get; set; } 
    public string Age { get; set; } 
    public int AgeValue => Convert.ToInt32(Age); 
} 
+0

感謝您回覆吉米。你提供的解決方案肯定會工作,但它會迫使我添加更多的數據(我知道可以忽略不計),邏輯(雖然不重要)和冗餘到我的模型(即..Person2ViewModel)。我很驚訝EF本身不支持這一點,因爲考慮到TSQL已經支持CAST和CONVERT,它似乎不是一個瘋狂的請求。我認爲9Rune5爲EF提供自定義函數的答案對我而言是一種更好的方法,因爲它消除了上面列出的負面因素,更符合當前映射/轉換的其餘部分。 – user1011627