我们有一个支持多种语言的遗留系统。特定于语言的字段在每个数据库行上都是重复的 - 每种语言都使用语言代码作为列名前缀。在我们的EF6模型中,我们使用LocalizedString复杂类型来保存每个字符串属性的所有翻译值。基于这篇文章:http://patrickdesjardins.com/blog/how-to-have-localized-string-with-mvc-and-entity-framework
我能够根据Web应用程序线程CurrentCulture定义映射,并使用EF6在linq投影中使用它。但我对视图模型中的映射代码的方式并不完全满意。
示例域类,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 Projection Queries的支持。假设我们突然不得不添加对新语言的支持,然后必须更新以更新许多视图模型。
内联网络运算符(?)被转换为SQL:CASE WHEN .... END语句,只从数据库加载正确的字段,这是非常好的。
你们有没有解决这个仍然支持LINQ查询投影的问题?
答案 0 :(得分:1)
您可以使用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”值。如果它在应用程序的生命周期内被读取一次,您可以采用硬编码的方式,如果它发生了变化,那么我的方式可以确保它通过查询进行参数化。
答案 1 :(得分:0)
这是更好的解决方案!谢谢!
为了支持来自内存中对象的映射,我假设需要额外的:
map.ConvertUsing(src =>
Context.TwoLetterISOLanguageName == "en" ? src.ValueEn :
Context.TwoLetterISOLanguageName == "da" ? src.ValueDa :
src.ValueNo);
var vm = Mapper.Map<List<CountryViewModel>>(list);