每次访问导航属性时是否读取? (EF4.1) [英] Are navigation properties read each time they are accessed? (EF4.1)

查看:97
本文介绍了每次访问导航属性时是否读取? (EF4.1)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我运行的一些示例查询:

  var discountsCount = product.Discounts.Count(); 
var currentDiscountsCount = product.Discounts.Count(d => d.IsCurrent);
var expiredDiscountsCount = product.Discounts.Count(d => d.IsExpired);

我想知道的是我的查询是否有意义,或表现不佳: / p>

我每次碰到数据库,还是会将结果从DbContext中的缓存数据中取出?



是如上所述,可以从头开始访问导航属性,或者我应该缓存它们,然后对它们执行更多查询,例如:

  var discounts = product.Discounts; 
var current = discounts.Count(d => d.IsCurrent);
var expired = discounts.Count(d => d.Expired);

如下所示的复杂情况如何,它会拉取整个集合,然后执行本地操作,或者是否构建专门的SQL查询,这意味着我无法重用结果,以避免再次触发数据库:

  var chained = discounts.OrderBy(d => d.CreationDate).Where(d => d.CreationDate< DateTime.Now).Count(); 

感谢您的建议!



<因此,一旦我调用了一个导航属性(它是一个集合),它将加载整个对象图。但是,如果我使用 .Count(d => d ...)过滤该集合,请选择(d => d ...) ) Min(d => d ...)等等。它是否加载整个图形,还是仅加载最终数据?

解决方案

product.Discounts (或任何其他导航集合)isn不是一个 IQueryable ,而只有一个 IEnumerable 。在 product.Discounts 中执行的LINQ操作永远不会向数据库发出查询,只有在延迟加载 product.Discounts 将从数据库加载一次到内存。它将被完全加载 - 无论您执行哪个LINQ操作或过滤器。



如果要在导航集合上执行过滤器或任何查询,而不将集合完全加载到内存中您不能访问导航集合,而是通过上下文创建查询,例如在您的示例中:

  c> var chained = context。 Entry(product).Collection(p => p.Discounts).Query()
.Where(d => d.CreationDate< DateTime.Now).Count();

这不会加载折扣 产品到内存中,但在数据库中执行查询,然后返回一个数字作为结果。这种下一个查询将再次转到数据库。


I am using EF 4.1, with POCOs which are lazy loaded.

Some sample queries that I run:

var discountsCount = product.Discounts.Count();  
var currentDiscountsCount = product.Discounts.Count(d=>d.IsCurrent);  
var expiredDiscountsCount = product.Discounts.Count(d=>d.IsExpired);  

What I'd like to know, is whether my queries make sense, or are poorly performant:

Am I hitting the database each time, or will the results come from cached data in the DbContext?

Is it okay to access the navigation properties "from scratch" each time, as above, or should I be caching them and then performing more queries on them, for example:

var discounts = product.Discounts;  
var current = discounts.Count(d=>d.IsCurrent);  
var expired = discounts.Count(d=>d.Expired);  

What about a complicated case like below, does it pull the whole collection and then perform local operations on it, or does it construct a specialised SQL query which means that I cannot reuse the results to avoid hitting the database again:

var chained = discounts.OrderBy(d=>d.CreationDate).Where(d=>d.CreationDate < DateTime.Now).Count();

Thanks for the advice!

EDIT based on comments below

So once I call a navigation property (which is a collection), it will load the entire object graph. But what if I filtered that collection using .Count(d=>d...) or Select(d=>d...) or Min(d=>d...), etc. Does it load the entire graph as well, or only the final data?

解决方案

product.Discounts (or any other navigation collection) isn't an IQueryable but only an IEnumerable. LINQ operations you perform on product.Discounts will never issue a query to the database - with the only exception that in case of lazy loading product.Discounts will be loaded once from the database into memory. It will be loaded completely - no matter which LINQ operation or filter you perform.

If you want to perform filters or any queries on navigation collections without loading the collection completely into memory you must not access the navigation collection but create a query through the context, for instance in your example:

var chained = context.Entry(product).Collection(p => p.Discounts).Query()
                     .Where(d => d.CreationDate < DateTime.Now).Count();

This would not load the Discounts collection of the product into memory but perform a query in the database and then return a single number as result. The next query of this kind would go to the database again.

这篇关于每次访问导航属性时是否读取? (EF4.1)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆