在调用链中,EF LINQ扩展Include()应该放在哪个位置?

6

当使用Entity Framework时,我很好奇include应该在调用链中的哪个位置被调用。

考虑下面的方法:

// sample usage from service layer
// _customerRepository.Paginate(1, out totalRecords, 25, "DateJoined DESC, AmountSpent", "DateJoined >= '2009-02-01'", "Invoices, Refunds");
public virtual IQueryable<T> Paginate(int page, out int total, int pageSize, string sort = "Id", string filter = null, string includes = null)
{
    IQueryable<T> query = DatabaseSet;

    total = query.Count(); // get total # of records (required for pagination)...
    var skipTo = GetValidSkipCount(page, total, pageSize);

    if (!String.IsNullOrWhiteSpace(filter))
    {
        query.Where(filter);
    }
    // should includes be before filtering? 
    // should query.Count() be called after query.Include? 
    // does it matter?
    if (!String.IsNullOrWhiteSpace(includes))
    {
        query.IncludeMany(includes); // my own extension that takes comma separated string of entities to include
    }

    return query.OrderBy(sort).Skip(skipTo).Take(pageSize);
}

我的问题是:

  1. 在调用链中,Include应该始终放在第一位吗?
  2. Count()是否受到Include的影响?如果是,我猜应该在Include之后进行Count
  3. 在筛选(Where)之前还是之后应该包括Include?
  4. 真的很重要吗,因为EF足够“聪明”可以自己解决一切?
1个回答

10

Include是否应始终位于调用链的第一位?

Include不必是链中的第一个。 Include是非常特殊的运算符,它不是查询的一部分。它就像查询的扩展。它也不是LINQ运算符——它是在ObjectQuery<T>IQueryable<T>扩展和DbQuery<T>版本都内部获取到此实现)上定义的EF运算符。 T定义了查询的形状和Include的根。只有当查询的结果形状与Include调用中使用的根匹配时,才会使用Include。因此,如果您在IQueryable<T>上添加Include调用,并且您的查询返回IQueryable<T>,则应用Include,但如果您的查询返回匿名类型的IQueryable,则更改了查询的形状,将不应用Include

Include是否会影响Count()?如果是,我想我应该在Include之后执行Count

如果您在查询上执行Count,则不使用IncludeCount执行查询并且不返回数据记录集——它更改了形状,因此没有任何内容可包含。

Include应在过滤(Where)之前还是之后?

这并不重要。Include创建连接,我期望EF(构建查询时)和数据库中的查询引擎(执行查询时)都应该在应用连接之前使用过滤。

是否真的很重要,因为EF足够“聪明”以找出所有内容?

只有当您更改查询的形状——使用投影或自定义连接时才会产生影响。在这种情况下,旧形状的Include将丢失(根本不使用)。


只是一个注释/问题,你在急加载时不也使用include吗? - Zapnologica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接