EF Core (LINQ) - 无法翻译查询表达式

EF Core (LINQ) - The Query expression could not be Translated

我有以下按参数搜索记录的查询。

DateTime CurrentDate = DateTime.Now;
var pastDueInvoices =  Context.Invoice.AsNoTracking()
                .Select(i => new InvoiceDTO
                {
                    ID = i.ID,
                    InvoiceNumber = i.InvoiceNumber
                    DaysPastDue =  i.Balance <= 0 ? 0 : CurrentDate.Subtract(i.InvoiceDate.AddDays(i.ProductNav.DiscountDays.GetValueOrDefault())).Days,
                });

然后我使用此查询仅显示 DaysPastDue > 0

的发票
 if (request.ShowPastDueInvoices)
{                    
  pastDueInvoices =  pastDueInvoices.Where(pd => pd.DaysPastDue > 0);
}

当我搜索过期发票时,出现以下错误

.Join( outer: DbSet, inner: i => EF.Property<Nullable>(i, "ProductID"), outerKeySelector: p => EF.Property<Nullable>(p, "ID"), innerKeySelector: (o, i) => new TransparentIdentifier<Invoice, Product>( Outer = o, Inner = i )) .Where(i => __CurrentDate_0.Subtract(i.Outer.InvoiceDate.AddDays((double)i.Inner.DiscountDays.GetValueOrDefault())).Days > 0)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync().

有帮助吗?

很可能 EF Core 无法将 Subtract 方法转换为 SQL。根据 this code EF core has a DateTime.AddDays provider built in but I was unable to find such a provider for Substract or DateDiff in the official documentation. So, you can try using EF.Functions which gives you access to DbFunctions class SQL 操作 EF.Functions.DateDiffDay 的辅助方法,即

DateTime CurrentDate = DateTime.Now;
var pastDueInvoices =  Context.Invoice.AsNoTracking()
            .Select(i => new InvoiceDTO
            {
                ID = i.ID,
                InvoiceNumber = i.InvoiceNumber
                DaysPastDue =  i.Balance <= 0 ? 0 : EF.Functions.DateDiffDay(CurrentDate, i.InvoiceDate.AddDays(i.ProductNav.DiscountDays.GetValueOrDefault())),
            });

我不确定这个 GetValueOrDefault() 方法是否会被转换为 SQL。如果它是您编写的一些自定义扩展方法,则很可能不是。也许你应该尝试用 i.ProductNav.DiscountDays ?? 0 之类的东西替换它,或者也许你不需要手动将 nullable 天列值转换为 0,很有可能 SQL 服务器将直接将空列值转换为 0 以用于 DATEADDSQL 函数。尝试两种情况。

此外,原始的 EF 6(非核心)版本将使用 DbFunctions

DateTime CurrentDate = DateTime.Now;
var pastDueInvoices =  Context.Invoice.AsNoTracking()
        .Select(i => new InvoiceDTO
        {
            ID = i.ID,
            InvoiceNumber = i.InvoiceNumber
            DaysPastDue =  i.Balance <= 0 ? 0 : DbFunctions.DiffDays(CurrentDate, DbFunctions.AddDays(i.InvoiceDate, i.ProductNav.DiscountDays)),
        })