EF Core中LINQ表达式无法翻译,带Where条件的查询报错如何解决?
错误原因
EF Core 3.0+版本调整了查询翻译规则,不支持无法转换为SQL的C#方法在服务端查询中执行,你当前在where子句中对数据库映射字段调用ToString(),EF Core无法将该方法翻译为对应SQL逻辑,因此抛出无法转换的报错。
修复方案
最优方案:提前转换参数类型(推荐)
不要在LINQ查询内部对数据库字段做类型转换,而是提前把你传入的过滤参数转换为和数据库字段完全匹配的类型,再做等值比对。
示例代码如下:
// 查询执行前先完成所有参数的类型转换,转换规则匹配数据库字段的实际类型即可 // 示例假设对应字段为bool类型,可根据实际业务调整转换逻辑 bool adviceExemptionVal = bool.Parse(AdviceExemption); bool refundExemptionVal = bool.Parse(RefundExemption); bool tipAdjustmentVal = bool.Parse(TipAdjustment); // 示例假设CoreBankingRecord为Guid类型,可根据实际类型调整转换逻辑 Guid regionVal = Guid.Parse(Region); queryable = (from merchantTerminalDetails in context.Posh5ProdMerchantTerminalDetails join merchantDetails in context.MerchantDetails on merchantTerminalDetails.MerchantRecord equals merchantDetails.Id join merchantContactDetails in context.Posh5ProdMerchantContactDetails on merchantDetails.Id equals merchantContactDetails.MerchantRecord // 直接用同类型字段比对,不需要调用ToString() where (merchantDetails.BypassAdviceVerification == adviceExemptionVal && merchantDetails.BypassCreditVerification == refundExemptionVal && merchantTerminalDetails.Tip == tipAdjustmentVal && merchantDetails.CoreBankingRecord == regionVal) select new OreDetails { MerchantRecord = merchantTerminalDetails.MerchantRecord, LegalName = merchantDetails.LegalName, PhoneNumber = merchantDetails.PhoneNumber, EmailAddress = merchantContactDetails.EmailAddress, TerminalId = merchantTerminalDetails.TerminalId, }).AsQueryable();
备用方案:客户端过滤(仅小数据量场景使用)
如果业务逻辑确实需要做特殊字符串比对,且查询返回的数据量很小,可以先把关联后的数据加载到内存再执行过滤,该方案会拉取所有关联数据到客户端,性能损耗较大,不推荐大数据量场景使用:
queryable = (from merchantTerminalDetails in context.Posh5ProdMerchantTerminalDetails join merchantDetails in context.MerchantDetails on merchantTerminalDetails.MerchantRecord equals merchantDetails.Id join merchantContactDetails in context.Posh5ProdMerchantContactDetails on merchantDetails.Id equals merchantContactDetails.MerchantRecord select new { merchantTerminalDetails, merchantDetails, merchantContactDetails }) // 加载到内存后再执行过滤 .AsEnumerable() .Where(x => x.merchantDetails.BypassAdviceVerification.ToString() == AdviceExemption && x.merchantDetails.BypassCreditVerification.ToString() == RefundExemption && x.merchantTerminalDetails.Tip.ToString() == TipAdjustment && x.merchantDetails.CoreBankingRecord.ToString() == Region) .Select(x => new OreDetails { MerchantRecord = x.merchantTerminalDetails.MerchantRecord, LegalName = x.merchantDetails.LegalName, PhoneNumber = x.merchantDetails.PhoneNumber, EmailAddress = x.merchantContactDetails.EmailAddress, TerminalId = x.merchantTerminalDetails.TerminalId, }).AsQueryable();
内容的提问来源于stack exchange,提问作者Adil15
相关产品推荐
相关产品推荐

