I have a data call in a Linq to Entities powered data access layer that is designed to make paged calls.
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.
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.
Is there a way to get count and a subset in the same operation?
The logical flow to me says we do the following:
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)
It's worth mentioning the data set is roughly 25,000 records, with over a dozen related tables that are searched in a 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:
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().
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.