使用 EF6 的自动映射器投影和 LINQ 查询

Automapper Projection and LINQ queries with EF6

我们有一个支持多种语言的遗留系统。特定于语言的字段在每个数据库行上都是重复的 - 每种语言都以语言代码作为列名前缀。在我们的 EF6 模型中,我们使用 LocalizedString 复杂类型来保存每个字符串 属性 的所有翻译值。基于本文:http://patrickdesjardins.com/blog/how-to-have-localized-string-with-mvc-and-entity-framework

我能够基于 Web 应用程序线程 CurrentCulture 定义映射,并使用 EF6 在 linq 投影中使用它。但是我对映射代码在视图模型中的方式并不完全满意。

示例域 class、ViewModel 和映射:


public partial class CountryDomain
{
    public CountryDomain()
    {
        CountryName = new LocalizedString();
    }

    public long CountryId { get; set; }
    public LocalizedString CountryName { get; set; }
    public string CountryCode { get; set; }
}

public class CountryViewModel
{
    public long CountryId { get; set; }
    public string CountryName { get; set; }
    public string CountryCode { get; set; }
}

public void CreateMap() 
{ 
Mapper.CreateMap<CountryDomain, CountryViewModel>()
  .ForMember(dest => dest.CountryName, opt => opt.MapFrom(src =>
     Context.TwoLetterISOLanguageName == "en" ? src.CountryName.ValueEn :
     Context.TwoLetterISOLanguageName == "da" ? src.CountryName.ValueDa :
     src.CountryName.ValueNo));

}


我想将 MapFrom 的内容移动到一个通用位置并仍然保留对 LINQ 投影查询的支持。假设我们突然需要添加对一种新语言的支持,然后必须记得更新很多视图模型。

内联三元运算符 (?) 被翻​​译成 SQL: CASE WHEN .... END 语句以仅从数据库加载正确的文件,这非常好。

你们有解决这个问题的方法,并且仍然支持 LINQ 查询中的投影吗?

您可以使用 ProjectUsing:

string lang = null;
Mapper.CreateMap<LocalizedString, string>().ProjectUsing(src =>
 lang == "en" ? src.ValueEn :
 lang == "da" ? src.ValueDa :
 src.ValueNo);

映射期间:

context.Countries.Project().To<CountryViewModel>(new { lang = Context.TwoLetterISOLanguageName });

我切换到参数化投影,因为我不确定 "Context" 值是否会根据请求更改。如果它在应用程序的生命周期内被读取一次,您可以采用硬编码的方式,如果它发生变化,那么我的方式确保它通过查询进行参数化。

这是更好的解决方案!谢谢!

为了支持内存中对象的映射,我假设需要额外的:


map.ConvertUsing(src =>    
    Context.TwoLetterISOLanguageName == "en" ? src.ValueEn :
    Context.TwoLetterISOLanguageName == "da" ? src.ValueDa :
    src.ValueNo);    

var vm = Mapper.Map<List<CountryViewModel>>(list);