布尔型异步调用的EF Core 3.1客户端评估问题

时间:2020-03-26 14:34:13

标签: c# .net-core entity-framework-core-3.1

我正在从.Net 2.1迁移到3.1,这包括EF Core升级。

现在我有了如下的LINQ查询,该查询没有任何问题:

var application = await _db.CustomerApplications
                .AsNoTracking()
                .Include(i => i.CustomerApplicationFields)
                .Include(i => i.Customer)
                .Where(x => x.Customer.PublicId == formId && x.IsPublished) // Also tried with &
                .OrderByDescending(o => o.Version)
                .FirstOrDefaultAsync();

使用EF Core 3.1时出现错误:

The LINQ expression 'DbSet<CustomerApplication>
    .Where(c => !(c.Deleted))
    .Join(
        outer: DbSet<Customer>
            .Where(c0 => !(c0.Deleted)), 
        inner: c => EF.Property<Nullable<long>>(c, "CustomerId"), 
        outerKeySelector: c0 => EF.Property<Nullable<long>>(c0, "Id"), 
        innerKeySelector: (o, i) => new TransparentIdentifier<CustomerApplication, Customer>(
            Outer = o, 
            Inner = i
        ))
    .Where(c => c.Inner.PublicId == __formId_0 && c.Outer.IsPublished)' 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(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

当我按以下方式转换此查询时,它就会起作用(将bool评估移到外面):

var application = await _db.CustomerApplications
                .AsNoTracking()
                .Include(i => i.CustomerApplicationFields)
                .Include(i => i.Customer)
                .Where(x => x.Customer.PublicId == formId)
                .OrderByDescending(o => o.Version)
                .ToListAsync();

var result = application.FirstOrDefault(x => x.IsPublished);

有人可以向我解释为什么这是一个问题吗?我还尝试了x.IsPublished == true,但没有任何效果。这似乎是随机的。

我还尝试了AsTracking()

2 个答案:

答案 0 :(得分:2)

在EF Core 3.0之前,无法在客户端转换为SQL查询的查询。现在,此行为已被消除,并且引发了异常,而不是在客户端上评估不可翻译的查询。

我还认为,当您分别编写 var result = application.FirstOrDefault(x => x.IsPublished); 时,新行为不应导致任何重大性能问题,因为同一件事之前发生过。以前不可见。 (如果这个假设是错误的,请纠正我!)

如果您要进行一个查询(未对此进行测试),也可以尝试以下方法:

var application = await _db.CustomerApplications
            .AsNoTracking()
            .Include(i => i.CustomerApplicationFields)
            .Include(i => i.Customer)
            .Where(x => x.Customer.PublicId == formId)
            .OrderByDescending(o => o.Version)
            .FirstOrDefaultAsync(x => x.IsPublished);

您可以在这里详细了解它:https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-3.0/breaking-changes#linq-queries-are-no-longer-evaluated-on-the-client

答案 1 :(得分:0)

您应该使用&&代替&,或者可以添加另一个where子句。