繁体   English   中英

实体框架代码优先 IQueryable 导航属性

[英]Entity Framework code-first IQueryable navigation property

我在互联网上看到的大多数示例都将导航属性显示为ICollection或直接List实现。 它们通常是virtual ,以启用延迟加载。

但是,当您访问此类属性时,它将在内存中加载整个集合,并且如果您在它之后有一个子查询(即object.MyListProperty.Where(...) ),我注意到将为每个项目发出一个 SQL 查询在MyListProperty

我如何避免这种情况? 如果可能,我希望 list 属性之后的where子句在 SQL 服务器上执行。 我可以使用IQueryable导航属性吗? 这种情况有什么最佳实践吗?

我对最佳实践的建议是完全禁用延迟加载。 相反,强制调用者通过包含语句或使用投影急切地加载导航属性。

有 3rd 方产品支持包含过滤器,如这篇文章中所述: 如何过滤实体框架中的包含实体,但根据我的经验,这使所检索对象的下游处理进一步复杂化。 如果实体对象是在方法X之外加载的,因为方法X无法确定导航属性是否已加载了正确的过滤器,方法X通过重新查询它知道它需要的精确行开始。

using (var context = new MyDbContext())
{
    context.Configuration.LazyLoadingEnabled = false;

    // TODO: load your data
    ...
}

这样,只有在明确请求时才会加载记录。

当您想要访问IQueryable以便延迟数据加载时,然后针对 DbContext实例而不是从对象进行这些查询。

  • 在这个例子中,假设一个Customer有成千上万的事务,所以我们根本不希望它们被急切延迟加载。
using (var context = new MyDbContext())
{
    context.Configuration.LazyLoadingEnabled = false;

    var customer = context.Customers.First(x => x.Id == 123);
    ...
    // count the transactions in the last 30 days for this customer
    int customerId = customer.Id;  
    DateTime dateFrom = DateTime.Today.AddDays(-30)

    // different variations on the same query
    int transactionCount1 = context.Customers.Where(x => x.Id == customerId)
                                             .SelectMany(x => x.Transactions.Where(x => x.TransactionDate >= dateFrom))
                                             .Count();
    int transactionCount2 = context.Customers.Where(x => x.Id == customerId)
                                             .SelectMany(x => x.Transactions)
                                             .Where(x => x.TransactionDate >= dateFrom)
                                             .Count();
    int transactionCount3 = context.Transactions.Where(x => x.CustomerId == customerId)
                                                .Where(x => x.TransactionDate >= dateFrom)
                                                .Count();
}

很高兴您已经确定要使用IQueryable<T>我们直接从DbContext访问它们,而不是从以前检索的实例中访问它们。

暂无
暂无

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

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