Entity Framework 4中关联翻译表查询的类型转换问题求助
解决EF4中Alert与Translation表的类型不匹配关联问题
针对你在EF4项目里遇到的多语言翻译关联问题——因为Alert.AlertTypeId是int类型,而Translation.Code是string类型,EF4的LINQ to Entities不支持直接用ToString()或强转来关联,我有两个可行的解决方案,都不需要修改EF版本或模型:
方案一:利用EF4支持的SQL函数在数据库层面转换类型
EF4提供了SqlFunctions类,其中的StringConvert方法可以将数值类型转换为字符串,并且能被EF转换成对应的SQL语句(STR()函数)。这样就能直接在数据库层面完成类型匹配,不需要把数据拉到内存:
using System.Data.Objects.SqlClient; // 需要引入这个命名空间 var list = from item in Alerts join itemTranslation in Translations // 注意:StringConvert只接受double类型,所以先把int转成double on SqlFunctions.StringConvert((double)item.AlertTypeId).Trim() equals itemTranslation.Code where itemTranslation.LanguageId == 1 && itemTranslation.FieldName == "AlertTypeEnum" select new { AlertId = item.AlertId, AlertTypeDescr = itemTranslation.Description };
注意:
StringConvert返回的字符串可能带有空格(比如STR(123)会返回' 123'),所以加上.Trim()确保和Code字段的格式一致。
方案二:先拉取翻译数据到内存,再用LINQ to Objects关联
如果不想依赖SqlFunctions,可以先把符合条件的翻译数据拉到本地内存,然后在内存里完成类型转换和关联(LINQ to Objects支持所有.NET方法):
// 先把目标语言的AlertTypeEnum翻译数据拉到内存,并转换Code为int var validTranslations = Translations .Where(m => m.LanguageId == 1 && m.FieldName == "AlertTypeEnum") .ToList() // 执行SQL,把数据拉到内存 .Select(t => { // 用TryParse避免无效格式的Code导致异常 if (int.TryParse(t.Code, out int codeInt)) { return new { CodeInt = codeInt, t.Description }; } return null; }) .Where(t => t != null); // 过滤掉转换失败的项 // 再把Alert数据拉到内存,和翻译数据关联 var list = Alerts.ToList() .Join(validTranslations, alert => alert.AlertTypeId, trans => trans.CodeInt, (alert, trans) => new { AlertId = alert.AlertId, AlertTypeDescr = trans.Description });
注意:这个方案适合翻译数据量不大的场景,如果Translation表数据很多,拉到内存可能影响性能。
为什么之前的方法失效?
EF4的LINQ to Entities会把LINQ表达式转换成SQL语句,但它只支持有限的.NET方法(比如Contains、Equals等),ToString()和直接强转(int)x.Code都不在支持列表里,所以无法转换成对应的SQL,导致报错。
内容的提问来源于stack exchange,提问作者Daniel 976034
相关产品推荐
相关产品推荐

