繁体   English   中英

实体框架 5(代码优先)导航属性

[英]Entity Framework 5 (Code First) Navigation Properties

在查询/过滤之前,使用导航属性的给定外键加载所有项目是否是实体框架的正确行为?

例如:

myUser.Apples.First(a => a.Id == 1 && !a.Expires.HasValue);

将加载与该用户关联的所有苹果。 (SQL 查询不查询 ID 或 Expires 字段)。

还有其他两种方法(生成正确的 SQL),但都没有使用导航属性那么干净:

myDbContext.Entry(myUser).Collection(u => u.Apples).Query().First(a => a.Id == 1 && !a.Expires.HasValue);

myDbContext.Apples.First(a => a.UserId == myUser.Id && a.Id == 1 && !a.Expires.HasValue);

我检查过的东西

  • 延迟加载已启用且未在任何地方禁用。
  • 导航属性是virtual

编辑:

好的,根据您的编辑,我认为我对您的要求有错误的想法(现在更有意义了)。 我将保留先前的答案,因为我认为它可能对解释有用,但与您的具体问题的相关性要低得多。

从您发布的内容来看,您的用户对象已启用延迟加载。 EF 默认启用延迟加载,但是延迟加载有一个要求,即将导航属性标记为虚拟(您已完成)。

延迟加载的工作原理是附加到导航属性上的 get 方法并在该点执行 SQL 查询以检索外部实体。 导航属性也不是可查询的集合,这意味着当您执行 get 方法时,您的查询将立即执行。

在上面的示例中,在执行 .first 调用之前枚举 User 上的 apples 集合(使用普通的旧 linq to objects 发生)。 这意味着 SQL 将返回与用户关联的所有苹果,并在查询机器的内存中过滤它们(如您所见)。 这也意味着您需要两个查询来下拉您感兴趣的苹果(一个用于用户,一个用于导航属性),如果您只想要苹果,这对您来说可能效率不高。

一个可能更好的方法是尽可能长时间地将整个表达式作为查询保留。 一个例子如下:

myDbContext.Users
   .Where(u=>u.Id == userId)
   .SelectMany(u=>u.Apples)
   .Where(a=>a.Id == 1 && !a.Expires.HasValue);

这应该作为单个 SQL 语句执行,并且只下拉你关心的苹果。

HTH


好的,根据我对您的问题的理解,您要问为什么 EF 似乎允许您在查询中使用导航属性,即使它们在结果集中可能为空。

回答您的问题是,这是预期的行为,原因如下:

为什么你写一个查询它被翻译成 SQL,例如像

myDbContext.Apples.Where(a=>a.IsRed)

会变成类似的东西

Select * from Apples
where [IsRed] = 1

类似地,以下内容也将被直接转换为 SQL

myDbContext.Apples.Where(a=>a.Tree.Height > 100)

会变成类似的东西

Select a.* from Apples as a
inner join Tree as t on a.TreeId = t.Id
where t.Height > 100

然而,当我们实际拉下结果集时,情况就有点不同了。

为了避免拉取太多数据并使其变慢,EF 提供了多种机制来指定结果集中返回的内容。 一个是延迟加载(顺便说一句,如果您想避免性能问题,则需要谨慎使用),第二个是包含语法。 这些方法限制了我们撤回的内容,以便查询快速且不会消耗不需要的资源。

例如在上面你会注意到只返回 Apple 字段。

如果我们如下添加一个包含,你可能会得到不同的结果:

myDbContext.Apples.Include(a=>a.Tree).Where(a=>a.Tree.Height > 100)

将转换为类似于以下内容的 SQL:

Select a.*, t.* from Apples as a
inner join Tree as t on a.TreeId = t.Id
where t.Height > 100

在你上面的例子中(我相当肯定它在语法上不正确,因为 myContext.Users 应该是一个集合,因此不应该有一个 .Apples)你正在创建一个查询,所有变量都可用。 当您枚举该查询时,您必须明确说明返回的内容。

有关导航属性及其工作原理(以及 .Include 语法)的更多详细信息,请查看我的博客: http : //blog.staticvoid.co.nz/2012/07/entity-framework-navigation-property.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM