代码之家  ›  专栏  ›  技术社区  ›  Keith Adler

使用Count和Take以及LINQ

  •  2
  • Keith Adler  · 技术社区  · 16 年前

    3 回复  |  直到 16 年前
        1
  •  6
  •   luke    16 年前

    你两个都可以。

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

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

    例如:如果你有两张桌子,说 Product ProductVersion 每个 产品 有多个 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() 您可能会也可能不会发生延迟加载。有时很难判断您是否有懒洋洋的问题,要检查您是否应该使用 DataContext.Log

        2
  •  4
  •   Stephen Cleary    16 年前

    最简单的方法就是 Count ,然后执行 Take :

    var q = ...;
    var count = q.Count();
    var result = q.Take(...);
    
        3
  •  2
  •   Ben Jenkinson    12 年前

    可以在一个linqtosql查询中实现这一点(其中只执行一条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;
    
    }