简体   繁体   English

使用 Linq to Entities 在一次操作中获取 COUNT 和 SKIP TAKE

[英]Getting COUNT and SKIP TAKE in one operation with Linq to Entities

I have a data call in a Linq to Entities powered data access layer that is designed to make paged calls.我在 Linq to Entities 支持的数据访问层中有一个数据调用,旨在进行分页调用。

In doing so, I need to select a subset of the data, say 50 rows, but also get the count of all matches to know how many total matches exist to be paged through.这样做时,我需要选择数据的一个子集,比如 50 行,但还要获取所有匹配项的计数,以了解有多少总匹配项需要分页。

Currently, I'm doing the following:目前,我正在执行以下操作:

var queryResult = DatabaseContext.Table
    .Where(x => !x.IsDeleted)
    .Where(p => (
            p.PropertyOne.ToLower().Contains(query) ||
            p.PropertyTwo.ToLower().Contains(query) 
            ));

int count = queryResult.Count();

var returnData = queryResult
    .OrderBy(i => i.ID)
    .Skip(start).Take((length))
    .Select(y => new ObjectDTO
    {
        PropertyOne = y.PropertyOne,
        PropertyTwo = y.PropertyTwo
    }
    .AsEnumerable();

This results in two costly database operations.这会导致两个代价高昂的数据库操作。 The COUNT operation for some reason actually takes longer than the SELECT operation.由于某种原因, COUNT操作实际上比SELECT操作花费的时间更长。

Is there a way to get count and a subset in the same operation?有没有办法在同一操作中获取计数和子集?

The logical flow to me says we do the following:对我来说,逻辑流程表明我们执行以下操作:

  • Look at Table看表
  • Find Items in Table that match a condition在表中查找符合条件的项目
  • Get a Count of all matches获取所有匹配项的计数
  • Return a numbered subset of the matches返回匹配的编号子集

This seems possible in one operation, but I cannot figure out how.这在一次操作中似乎是可能的,但我不知道如何。

Attempt One, Slower尝试一,慢

Tried D Stanley's suggestion of casting the full result set to a List and doing count and memory in paging, but it is roughly 2x slower (6.9s avg vs 3.9s avg)尝试了 D Stanley 将完整结果集转换为List并在分页中进行计数和内存的建议,但它的速度大约慢了 2 倍(平均 6.9 秒 vs 平均 3.9 秒)

It's worth mentioning the data set is roughly 25,000 records, with over a dozen related tables that are searched in a JOIN.值得一提的是,该数据集大约有 25,000 条记录,在 JOIN 中搜索了十几个相关表。

It may be possible, but it probably won't be much faster because of the criteria you're using.这可能是可能的,但由于您使用的标准,它可能不会更快。 Since you're searching for text within a column value, you cannot use an index and thus must do a table scan.由于您要在列值中搜索文本,因此不能使用索引,因此必须进行表扫描。 You could do a single query to get all records and do the Count and Skip/Take in linq-to-objects:可以执行单个查询来获取所有记录并在 linq-to-objects 中执行CountSkip/Take

var queryResult = DatabaseContext.Table
    .Where(x => !x.IsDeleted)
    .OrderBy(i => i.ID)
    .Where(p => (
            p.PropertyOne.ToLower().Contains(query) ||
            p.PropertyTwo.ToLower().Contains(query) 
            ))
    .ToList();

int count = queryResult.Count();  // now this will be a linq-to-objects query

var returnData = queryResult
    .Skip(start).Take((length))
    .AsEnumerable();

but you'd have to try it to see if it would be any faster.但是您必须尝试一下,看看它是否会更快。

How about something like this:像这样的东西怎么样:

db.Products
   .Take(10)
   .Select(p => new 
                {
                    Total = db.Products.Count, 
                    Product = p
                })

If that's no good, it may help to know that in SQL, you get the total results and one page of them using OVER().如果这不好,了解在 SQL 中使用 OVER() 获得总结果和其中一页可能会有所帮助。

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

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