有没有一种方法可以在不使数据库受到两次查询或编写2个单独的查询的情况下获取复杂Linq查询和数百万记录的行计数?
我可能有自己的建议。编写存储过程,但我擅长MySQL而不是MSSQL。
如果有更好的建议,那就太棒了。此外,如果有人知道Microsoft是否正在将此功能添加到实体框架中。
有没有一种方法可以在不使数据库受到两次查询或编写2个单独的查询的情况下获取复杂Linq查询和数百万记录的行计数?
我可能有自己的建议。编写存储过程,但我擅长MySQL而不是MSSQL。
如果有更好的建议,那就太棒了。此外,如果有人知道Microsoft是否正在将此功能添加到实体框架中。
我建议使用Take()函数。这个函数可以用来指定从LINQ查询或列表中获取的记录数。例如:
List<customers> _customers = (from a in db.customers select a).ToList();
var _dataToWebPage = _customers.Take(50);
在我的MVC应用程序中,我使用类似的技术将_customers列表写入会话,然后在用户点击第2页、第3页等时使用此列表进行进一步的分页查询。这样可以避免多次访问数据库。但是,如果您的列表非常大,则将其写入会话可能不是一个好主意。
对于分页,您可以同时使用Skip()和Take()函数。例如,要获取数据的第2页:
var _dataToWebPage = _customers.Skip(50).Take(50);
Take(50)
之前调用 ToList()
表示你会拉取所有的记录到你的应用程序中。在让服务器执行所有这些工作后,最终只会保留其中的 50 条记录。因此,在调用 ToList()
之前应该先调用 Take(50)
。 - Don Cheadlepublic async Task<IList<SavedSearch>> FindAllSavedSearches(int page, int limit)
{
if (page == 0)
page = 1;
if (limit == 0)
limit = int.MaxValue;
var skip = (page - 1) * limit;
var savedSearches = _databaseContext.SavedSearches.Skip(skip).Take(limit).Include(x => x.Parameters);
return await savedSearches.ToArrayAsync();
}
我对Entity Framework没有经验,也没有测试过其性能,因此请谨慎使用 :)
select count() over(), table.* from table
count() over()
会返回结果中总行数的计数,因此您无需运行两个查询。
请记住,您应该在上下文中运行原始SQL或使用Dapper,它将结果作为视图模型返回。var products = await _context.Products.ToPagedListAsync(pageNumber, pageSize)
我创建了一个NuGet库,可以为您完成分页。https://github.com/wdunn001/EntityFrameworkPaginateCore
将NuGet添加到项目中
安装-Package EntityFrameworkPaginateCore 添加
使用EntityFrameworkPaginateCore; 到您的提供程序
有1个方法和2个重载方法,这些重载方法允许排序和过滤。使用sort对象和filter对象
public async Task<Page<Example>> GetPaginatedExample(
int pageSize = 10,
int currentPage = 1,
string searchText = "",
int sortBy = 2
)
{
var filters = new Filters<Example>();
filters.Add(!string.IsNullOrEmpty(searchText), x => x.Title.Contains(searchText));
var sorts = new Sorts<Example>();
sorts.Add(sortBy == 1, x => x.ExampleId);
sorts.Add(sortBy == 2, x => x.Edited);
sorts.Add(sortBy == 3, x => x.Title);
try
{
return await _Context.EfExample.Select(e => _mapper.Map<Example>(e)).PaginateAsync(currentPage, pageSize, sorts, filters);
}
catch (Exception ex)
{
throw new KeyNotFoundException(ex.Message);
}
}
select count() from table
SQL语句 - 因此,虽然您确实需要2个查询,但其中一个查询非常便宜。 - JK.select count()
一点也不便宜!实际上,它的复杂度几乎与实际获取数据相同,唯一的区别是它只计算行数而不是获取行。但它仍然必须执行所有扫描等操作。 - Vladimir Perevalov