使用Count with Take with LINQ

时间:2010-05-18 04:03:29

标签: c# linq

使用Take运算符时,有没有办法获得整数?

3 个答案:

答案 0 :(得分:6)

你可以做到这两点。

IEnumerable<T> query = ...complicated query;
int c = query.Count();
query = query.Take(n);

只需在拍摄前执行计数。这将导致查询执行两次,但我相信这是不可避免的。

如果这是在Linq2SQL上下文中,正如您的注释所暗示的那么这实际上会查询数据库两次。就延迟加载而言,它将取决于查询结果的实际使用方式。

例如:如果您有两个表ProductProductVersion,其中每个Product都有多个ProductVersions通过外键关联。

如果这是您的查询:

var query = db.Products.Where(p => complicated condition).OrderBy(p => p.Name).ThenBy(...).Select(p => p);

您只是选择Products但执行查询后

var results = query.ToList();//forces query execution
results[0].ProductVersions;//<-- Lazy loading occurs

如果您引用任何不属于原始查询的外键或相关对象,那么它将被延迟加载。在您的情况下,计数不会导致任何延迟加载,因为它只是返回一个int。但是根据您对Take()的结果实际执行的操作,您可能会或可能不会进行延迟加载。有时候很难判断你是否有LazyLoading ocurring,要检查你是否应该使用DataContext.Log属性来记录你的查询。

答案 1 :(得分:4)

最简单的方法是只执行Count查询,然后执行Take

var q = ...;
var count = q.Count();
var result = q.Take(...);

答案 2 :(得分:2)

可以在单个Linq-to-SQL查询中执行此操作(其中只执行一个SQL语句)。生成的SQL会让看起来不愉快,因此您的性能可能会有所不同。

如果这是您的查询:

IQueryable<Person> yourQuery = People
    .Where(x => /* complicated query .. */);

您可以将以下内容添加到其中:

var result = yourQuery
    .GroupBy (x => true) // This will match all of the rows from your query ..
    .Select (g => new {
        // .. so 'g', the group, will then contain all of the rows from your query.
        CountAll = g.Count(),
        TakeFive = g.Take(5),
        // We could also query for a max value.
        MaxAgeFromAll = g.Max(x => x.PersonAge)
    })
    .FirstOrDefault();

您可以这样访问您的数据:

// Check that result is not null before access.
// If there are no records to find, then 'result' will return null (because of the grouping)
if(result != null) {

    var count = result.CountAll;

    var firstFiveRows = result.TakeFive;

    var maxPersonAge = result.MaxAgeFromAll;

}