有没有一种方法可以获取复杂 Linq 查询的行数和数百万条记录,而无需两次访问数据库或编写 2 个单独的查询?
我可能有我自己的建议。写一个存储过程,但我擅长 MySQL 而不是 MSSQL。
任何更好的建议都会很棒。另外,如果有人知道微软是否正在努力将此功能添加到实体框架中。
有没有一种方法可以获取复杂 Linq 查询的行数和数百万条记录,而无需两次访问数据库或编写 2 个单独的查询?
我可能有我自己的建议。写一个存储过程,但我擅长 MySQL 而不是 MSSQL。
任何更好的建议都会很棒。另外,如果有人知道微软是否正在努力将此功能添加到实体框架中。
我建议使用 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);
我最近受到(复制自)这篇代码项目文章 实体框架分页的启发
编码:
public 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();
}
我没有使用实体框架的经验,也没有测试过它的性能,所以请谨慎使用:)
显示数百万条记录的常用方法是不显示所有页面。想一想:如果您有数百万条记录,例如每页 20 甚至 100 项,那么您将拥有数万页。把它们都展示出来是没有意义的。您可以简单地加载当前页面并提供指向下一页的链接,就是这样。或者您可以加载 100-500 条记录,但仍然只显示一个页面并使用加载的记录信息为前几页生成页面链接(因此要确定有多少下一页可用)。
如果您需要快速解决方案,可以使用 XPagedList https://github.com/dncuug/X.PagedList。XPagedList 是一个库,可让您轻松获取 IEnumerable/IQueryable,将其分割成“页面”,并通过索引获取特定“页面”。例如
var products = await _context.Products.ToPagedListAsync(pageNumber, pageSize)
在 sql server 上很容易。你可以写这个查询:
select count() over(), table.* from table
count () over() 将返回结果中的总行数,因此您不需要运行两个查询。请记住,您应该在上下文中运行原始 sql 或使用返回结果的 dapper 作为视图模型
我创建了一个为您进行分页的 nuget 库。https://github.com/wdunn001/EntityFrameworkPaginateCore
将nuget添加到项目
安装包 EntityFrameworkPaginateCore 添加
使用 EntityFrameworkPaginateCore;给你的供应商
有 1 个方法和 2 个重载,该方法重载允许排序和过滤。使用排序对象和过滤器对象
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);
}
}