简体   繁体   English

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

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

Is it the correct behaviour of entity framework to load all items with the given foreign key for a navigation property before querying/filtering?在查询/过滤之前,使用导航属性的给定外键加载所有项目是否是实体框架的正确行为?

For example:例如:

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

Will load all apples associated with that user.将加载与该用户关联的所有苹果。 (The SQL query doesn't query the ID or Expires fields). (SQL 查询不查询 ID 或 Expires 字段)。

There are two other ways of doing it (which generate the correct SQL) but neither as clean as using the navigation properties:还有其他两种方法(生成正确的 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);

Things I've Checked我检查过的东西

  • Lazy load is enabled and is not disabled anywhere.延迟加载已启用且未在任何地方禁用。
  • The navigation properties are virtual .导航属性是virtual

EDIT:编辑:

Ok based on your edit I think i had the wrong idea about what you were asking (which makes a lot more sense now).好的,根据您的编辑,我认为我对您的要求有错误的想法(现在更有意义了)。 Ill leave the previous answer around as i think its probably useful to explain but is much less relevant to your specific question as it stands.我将保留先前的答案,因为我认为它可能对解释有用,但与您的具体问题的相关性要低得多。

From what you've posted your user object is enabled for lazy loading.从您发布的内容来看,您的用户对象已启用延迟加载。 EF enables lazy loading by default, however there is one requirement to lazy loading which is to mark navigation properties as virtual (which you have done). EF 默认启用延迟加载,但是延迟加载有一个要求,即将导航属性标记为虚拟(您已完成)。

Lazy loading works by attaching to the get method on a navigation property and performing a SQL query at that point to retrieve the foreign entity.延迟加载的工作原理是附加到导航属性上的 get 方法并在该点执行 SQL 查询以检索外部实体。 Navigation properties are also not queriable collections, which means that when you execute the get method your query will be executed immediately.导航属性也不是可查询的集合,这意味着当您执行 get 方法时,您的查询将立即执行。

In your above example the apples collection on User is enumerated before you execute the .first call (which occurs using plain old linq to objects).在上面的示例中,在执行 .first 调用之前枚举 User 上的 apples 集合(使用普通的旧 linq to objects 发生)。 This means that SQL will return back all of the apples associated to the user and filter them in memory on the querying machine (as you have observed).这意味着 SQL 将返回与用户关联的所有苹果,并在查询机器的内存中过滤它们(如您所见)。 This will also mean you need two queries to pull down the apples you are interested in (one for the user and one for the nav property) which may not be efficient for you if all you want is apples.这也意味着您需要两个查询来下拉您感兴趣的苹果(一个用于用户,一个用于导航属性),如果您只想要苹果,这对您来说可能效率不高。

A perhaps better way of doing this is to keep the whole expression as a query for as long as possible.一个可能更好的方法是尽可能长时间地将整个表达式作为查询保留。 An example of this would be something like the following:一个例子如下:

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

this should execute as a single SQL statement and only pull down the apples you care about.这应该作为单个 SQL 语句执行,并且只下拉你关心的苹果。

HTH HTH


Ok from what i can understand of your question you are asking why EF appears to allow you to use navigation properties in a query even though they may be null in the result set.好的,根据我对您的问题的理解,您要问为什么 EF 似乎允许您在查询中使用导航属性,即使它们在结果集中可能为空。

In answer to your question yes this is expected behavior, heres why:回答您的问题是,这是预期的行为,原因如下:

Why you write a query it is translated into SQL, for example something like为什么你写一个查询它被翻译成 SQL,例如像

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

will turn into something like会变成类似的东西

Select * from Apples
where [IsRed] = 1

similarly something like the following will also be translated directly to SQL类似地,以下内容也将被直接转换为 SQL

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

will turn into something like会变成类似的东西

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

However its a bit of a different story when we actually pull down the result sets.然而,当我们实际拉下结果集时,情况就有点不同了。

To avoid pulling down too much data and making it slow EF offers several mechanisms for specifying what comes back in the result set.为了避免拉取太多数据并使其变慢,EF 提供了多种机制来指定结果集中返回的内容。 One is lazy loading (which incidently needs to be used carefully if you want to avoid performance issues) and the second is the include syntax.一个是延迟加载(顺便说一句,如果您想避免性能问题,则需要谨慎使用),第二个是包含语法。 These methods restrict what we are pulling back so that queries are quick and dont consume un-needed resources.这些方法限制了我们撤回的内容,以便查询快速且不会消耗不需要的资源。

For example in the above you will note that only Apple fields are returned.例如在上面你会注意到只返回 Apple 字段。

If we were to add an include to that as below you could get a different result:如果我们如下添加一个包含,你可能会得到不同的结果:

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

will translate to SQL similar to:将转换为类似于以下内容的 SQL:

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

In your above example (which I'm fairly sure isn't syntactically correct as myContext.Users should be a collection and therefore shouldn't have a .Apples) you are creating a query therefor all variables are available.在你上面的例子中(我相当肯定它在语法上不正确,因为 myContext.Users 应该是一个集合,因此不应该有一个 .Apples)你正在创建一个查询,所有变量都可用。 When you enumerate that query you have to be explicit about whats returned.当您枚举该查询时,您必须明确说明返回的内容。

For more details on navigation properties and how they work (and the .Include syntax) check out my blog: http://blog.staticvoid.co.nz/2012/07/entity-framework-navigation-property.html有关导航属性及其工作原理(以及 .Include 语法)的更多详细信息,请查看我的博客: http : //blog.staticvoid.co.nz/2012/07/entity-framework-navigation-property.html

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

相关问题 在视图(实体框架6 + MVC 5)中设置查询,导航属性(“代码优先”) - Setup query, navigation properties (Code First) in view (Entity Framework 6 + MVC 5) code -first实体框架 - 继承和导航属性是否可行? - code -first Entity framework - Is this possible with inheritance and navigation properties? 实体框架代码首先使用导航属性一键 - Entity framework code first using navigation properties a Key .NET Entity Framework 代码优先:未加载导航属性 - .NET Entity Framework code-first: navigation properties are not loaded 在创建时分配实体框架代码优先导航属性 - Assigning Entity Framework Code First Navigation Properties on Create 实体框架-代码优先/ Fluent API-过滤的导航属性 - Entity Framework - Code First / Fluent API - Filtered navigation properties 实体框架代码优先导航问题 - Entity Framework Code First navigation issue 实体框架6.1:代码优先导航属性没有在数据库中定义的对应键 - Entity Framework 6.1: Code First navigation properties that do not have corresponding keys defined in database 实体框架6代码首先处理阴影属性 - Entity Framework 6 code first handing shadow properties 实体框架:导航属性-代码优先 - Entity Framework: Navigational properties - Code First
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM