6

我很好奇在使用实体框架时应该在调用链中的哪个位置调用。考虑以下方法:

// 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 的影响吗?如果是这样,我想我应该在包含后进行计数
  3. 应该包括在过滤之前还是之后(在哪里)?
  4. 这真的很重要,因为 EF 足够“聪明”,可以弄清楚所有事情吗?
4

1 回答 1

10

Include 应该始终位于调用链的首位吗?

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

Count() 会受到 Include 的影响吗?如果是这样,我想我应该在包含后进行计数

Include如果Count对查询执行,则不使用。Count执行查询并且它不返回数据记录集 - 它改变了形状并且没有任何内容可以包含。

应该包括在过滤之前还是之后(在哪里)?

没关系。包括创建连接,我希望 EF(构建查询时)和数据库中的查询引擎(执行查询时)都应该在应用连接之前使用过滤。

这真的很重要,因为 EF 足够“聪明”,可以弄清楚所有事情吗?

仅当您更改查询的形状时才重要 - 您使用投影或自定义连接。在这种情况下Include,以前的形状将丢失(根本不使用)。

于 2012-06-05T17:32:35.110 回答