在分页Product对象列表时,我遇到了Entity Framework和Linq的性能问题:
var data =_service.GetAll();
var page = data.Skip((index) * pageSize).Take(pageSize);
list.Add(page.AsEnumerable); // ** its slow right here
我的测试数据库中有1958个产品,但是当上面的代码运行时,我可以看到3916(即1958 * 2)执行的单独查询(通过查看sql profiler)。
Product类看起来像:
public class Product
{
public virtual int Id {get;set;}
public virtual string ProductCode {get;set;}
//..etc other properties
public virtual ICollection<WarehouseProduct> WarehouseProducts { // etc }
public virtual ICollection<InvoiceLine> InvoiceLines { // etc }
// etc other navigation properties
}
在sql profiler中,我可以看到此查询执行了3916次:
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[ProductId] AS [ProductId],
// etc
FROM [dbo].[WarehouseProducts] AS [Extent1]
我做错了什么? Product对象具有12种不同的导航属性,但仅查询了WarehouseProduct 3916次。请注意,该查询没有WHERE子句,但两个表之间存在外键关系(这就是导航属性的原因)
答案 0 :(得分:3)
获得产品后,您必须访问Product.WarehouseProducts
,所以
如果您使用的是实体,则需要使用Products.Include("WarehouseProduct").Include("InvoiceLine")
在GetAll()
方法中,它会告诉实体在同一查询中检索数据。
默认情况下,相关实体是延迟加载的,因此如果您不使用Include()
指定要在结果中包含哪些相关实体,那么每次访问代码中的相关实体时,都会触发另一个数据库查找。
答案 1 :(得分:0)
page.AsEnumerable
导致查询序列被评估和具体化。前面的语句(假设仍然启用了延迟加载并且您正在查询SQL数据源)正在设置构成要执行的SQL语句的条件。
您没有发布GetAll()方法,因此这可能是您的附加记录的来源。
生成的SQL查询应该有一个TOP作为select的一部分,它应该返回一个包含多个记录的结果集,因此您可能无法分析正确的查询。