如上所述in "Loading Related Data" from EF Core Documentation,我们可以使用.Include(..)
从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; }
}
..然后以下代码应该有效:
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");
*/
但事实并非如此。
我注意到如果查询未返回最初请求的类型,则可以忽略.Include()
:
如果更改查询以使其不再返回查询开头的实体类型的实例,则忽略包含运算符。 [snip]默认情况下,EF Core会在忽略include运算符时记录警告。
我不确定在.Any()
的上述调用中是如何相关的。是的,查询没有返回原始类型(当然它返回bool
)但同时,也没有记录警告以告知它被忽略。
我的问题是:
.ToList()
),但这显然会加载所有内容,以确定.Any()
上是否有任何内容这可能很容易成为一个查询(在EF6中也是如此)。什么是使.Any()
在服务器端工作的解决方法,因此不需要ToList将其放入内存?解决方法:
context.TestEntityAs
.Include(m => m.TestEntityB)
.ToList()
.Any(m => m.BProperty == "Hello World");
完全可重复的样本:https://gist.github.com/rudiv/3aa3e1bb65b86ec78ec6f5620ee236ab
答案 0 :(得分:0)
行为是预期的,但您可以使用显式加载来进行更有效的查询,如下所示。
2个单独的查询,但无需加载所有TestEntityBs
// 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));
答案 1 :(得分:0)
按照命名约定应该可以工作 您可以尝试使用这段代码来手动配置模型之间的关系
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TestEntityA>()
.HasOne(x => x.TestEntityB)
.WithMany()
.HasForeignKey(x => x.TestEntityBId);
}
答案 2 :(得分:0)
我不确定,但试试 [ForeignKey(nameof(TestEntityBId))]
public class TestEntityA
{
public int Id { get; set; }
public int TestEntityBId { get; set; }
[ForeignKey(nameof(TestEntityBId ))] 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; }
}