LINQ表达式错误无法翻译

时间:2020-10-07 16:42:06

标签: c# entity-framework linq

我在尝试执行查询时遇到此错误。

System.InvalidOperationException: .where(ti =>(int)ti.Inner.OptionType == 1 && ti.Inner.QualifierId == null && ti.Inner.CreditingMethod!=“ xxx” && __ToList_0 .Any(e => e.Vdate ==(Nullable)ti.Outer.ADate))'无法翻译。以一种可以翻译的形式重写查询,或者通过插入对AsEnumerable(),AsAsyncEnumerable(),ToList()或ToListAsync()的调用来显式切换到客户端评估。有关更多信息,请参见https://go.microsoft.com/fwlink/?linkid=2101038

我正在填充的对象是

public class OCList
    {
        public DateTime? Vdate{ get; set; }
        public Double? VWeight{ get; set; }
    }

/// example of adding to the list
List<OCList> ocList= new List<OCList>();
            if (request.Date1 != null && request.Weight1 != null)
            {
                ocList.Add(new OCList{ Vdate = request.Date1.Value, VWeight = request.Weight1.Value });
            }

错误在这里:

&& ocList.ToList().Any(e => e.Vdate == x.Tb2.ADate))

Linq表达式:

var results = _context.Tb1
                .Join(_context.Tb2, oc => oc.OptionId, o => o.OptionId, (oc, o) => new { OptionCost = oc, Option = o })
                .Where(x => x.Tb2.Val1 == 1 
                    && x.Tb2.Val2 == null 
                    && ocList.ToList().Any(e => e.Vdate == x.Tb2.ADate))
                ////.........

1 个答案:

答案 0 :(得分:0)

在此处检查客户端和服务器端评估:https://docs.microsoft.com/en-us/ef/core/querying/client-eval

EF Core在顶级投影中支持部分客户评估(实际上是对Select()的最后一次调用)。如果查询中的顶级投影无法转换到服务器,则EF Core将从服务器获取所有必需的数据,并在客户端上评估查询的其余部分。如果EF Core在顶级投影之外的任何其他位置检测到无法转换到服务器的表达式,则它将抛出运行时异常。

您的ToListAny无法转换为sql,因此您会收到错误消息。

这可以工作

var results = _context.Tb1
                .Join(_context.Tb2, oc => oc.OptionId, o => o.OptionId, (oc, o) => new { OptionCost = oc, Option = o })
                .AsEnumerable()
                .Where(x => x.Tb2.Val1 == 1 
                    && x.Tb2.Val2 == null 
                    && ocList.ToList().Any(e => e.Vdate == x.Tb2.ADate))

但是它将首先从服务器获取所有内容,然后应用where子句,从而导致性能下降。

您可以像这样使它变得更好

var results = _context.Tb1
                .Join(_context.Tb2, oc => oc.OptionId, o => o.OptionId, (oc, o) => new { OptionCost = oc, Option = o })
                .Where(x => x.Tb2.Val1 == 1 
                    && x.Tb2.Val2 == null)
                .AsEnumerable()
                 .Where(ocList.ToList().Any(e => e.Vdate == x.Tb2.ADate))