实体框架核心忽略.Include(..)而没有.ToList(..)间接

Rud*_*ser 8 c# entity-framework entity-framework-core .net-core asp.net-core

EF Core Documentation中的"加载相关数据"中所述,我们可以使用.Include(..)Eagerly加载导航属性DbSet(或通用IQueryable<T>链接回EF上下文).

这意味着,给定以下模型:

public class TestEntityA
{
    public int Id { get; set; }
    public int TestEntityBId { get; set; }
    public TestEntityB TestEntityB { get; set; }

    public string BProperty { get { return TestEntityB.Property; } }
}

public class TestEntityB
{
    public int Id { get; set; }
    public string Property { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

..然后以下代码应该工作:

context.TestEntityAs
    .Include(m => m.TestEntityB)
    .Any(m => m.BProperty == "Hello World");
    /*
     * Note that the below DOES work by using the nav property directly
     * in the query, but that is not always going to be an option for
     * whatever reason. If it's .Included it should be available through
     * INNER JOINing it into the base query before the .Any runs.
     * .Any(m => m.TestEntityB.Property == "Hello World");
     */
Run Code Online (Sandbox Code Playgroud)

但事实并非如此.

我注意到如果.Include()查询没有返回最初请求的类型,可以忽略一个警告:

如果更改查询以使其不再返回查询开头的实体类型的实例,则忽略包含运算符.[snip]默认情况下,EF Core会在忽略include运算符时记录警告.

在上面的调用中.Any(),我不确定如何相关.是的,查询没有返回原始类型(它bool当然是返回)但同时,也没有记录警告以提示它被忽略.

我的问题是:

  • 这是一个预计会起作用的用例吗?我应该在EF Core中提出错误吗?
  • 如果它没有预期,一个解决方法是如下(叫.ToList()),但显然会加载的一切,找出如果我们有一个东西.Any()它可以很容易地查询(并会因此在EF6).什么是.Any()在服务器端使其工作的解决方法,因此不需要ToList将其放入内存?

解决方法:

context.TestEntityAs
    .Include(m => m.TestEntityB)
    .ToList()
    .Any(m => m.BProperty == "Hello World");
Run Code Online (Sandbox Code Playgroud)

完全可重复的样本:https://gist.github.com/rudiv/3aa3e1bb65b86ec78ec6f5620ee236ab

Iva*_*azz 0

该行为是预期的,但您可以使用显式加载来实现更高效的查询,如下所示。

2 个单独的查询,但无需加载所有 TestEntityB

// First query
var testEntityAs = context.TestEntityAs.ToList();
var testEntityAsIds = testEntityAs.Select(t => t.Id);

// Second query, can apply filter of Hello World without loading all TestEntityBs
context.TestEntityBs
    .Where(t => testEntityAsIds.Contains(t.Id) && t.Property == "Hello World")
    .Load();

// In memory check
var isAny = testEntityAs.Any(t => !string.IsNullOrEmpty(t.BProperty));
Run Code Online (Sandbox Code Playgroud)