Entity framework 如何将LINQ contains查询与所有记录的计数相结合,以及如何检索具有偏移量的记录

Entity framework 如何将LINQ contains查询与所有记录的计数相结合,以及如何检索具有偏移量的记录,entity-framework,linq,asp.net-core,entity-framework-core,azure-sql-database,Entity Framework,Linq,Asp.net Core,Entity Framework Core,Azure Sql Database,我有一个分页和搜索电影的页面,电影表有388262条记录。如果不使用搜索,下面的代码工作得很快。但是当使用search(vm.search已填充)时,检索记录的速度会变慢 基本上,它会执行两次contains/like查询,一次用于返回带偏移量的结果,另一次用于不带偏移量的计数,这是正确的,但是有没有一种方法可以结合使用以提高性能 奇怪的是,当我使用日志中的查询并使用SSMS(SQLServerManagementStudio)直接在数据库上执行它们时。它在大约2秒钟内相当快地执行这两个查询。当

我有一个分页和搜索电影的页面,电影表有388262条记录。如果不使用搜索,下面的代码工作得很快。但是当使用search(vm.search已填充)时,检索记录的速度会变慢

基本上,它会执行两次contains/like查询,一次用于返回带偏移量的结果,另一次用于不带偏移量的计数,这是正确的,但是有没有一种方法可以结合使用以提高性能

奇怪的是,当我使用日志中的查询并使用SSMS(SQLServerManagementStudio)直接在数据库上执行它们时。它在大约2秒钟内相当快地执行这两个查询。当它用代码/linq执行时,大约需要10秒

执行LINQ的代码:

public IActionResult索引(MovieIndexViewModel-vm){
IQueryable query=\u movieRepository.GetQueryable().AsNoTracking()
.选择(m=>新电影{
movie\u id=m.movie\u id,
title=m.title,
description=m.description
});
如果(!string.IsNullOrWhiteSpace(vm.Search)){
query=query.Where(m=>m.title.Contains(vm.Search));
}
vm.Movies=query.Skip(_pageSize*(vm.Page-1)).Take(_pageSize.ToList();
vm.PageSize=\u PageSize;
vm.TotalItemCount=query.Count();
返回视图(vm);
}
使用Skip and Take命令行中的SQL日志:

选择[m].[movie\u id],[m].[title],[m].[description]
从[电影]到[m]
其中[m].[title]类似于('%'+@@虚拟机搜索0)+'%
按@@ROWCOUNT排序
偏移量0行仅取下30行
包含计数的行中的SQL日志:

选择计数(*)
从[电影]到[m]
其中[m].[title]类似于('%'+@@虚拟机搜索0)+'%

下面的代码将同时运行这两个查询。但是,这段代码只会更快地执行~[latency to SQL server],应该在10毫秒左右

public async Task<IActionResult> Index(MovieIndexViewModel vm) {
    IQueryable<Movie> query = _movieRepository.GetQueryable().AsNoTracking()
        .Select(m => new Movie {
            movie_id = m.movie_id,
            title = m.title,
            description = m.description
        });

    if (!string.IsNullOrWhiteSpace(vm.Search)) {
        query = query.Where(m => m.title.Contains(vm.Search));
    }
    var moviesTask = query.Skip(_pageSize * (vm.Page - 1)).Take(_pageSize).ToListAsync();
    var countTask = query.CountAsync();
    vm.Movies = await moviesTask;
    vm.PageSize = _pageSize;
    vm.TotalItemCount = await countTask;
    return View(vm);
}
public异步任务索引(MovieIndexViewModel-vm){
IQueryable query=\u movieRepository.GetQueryable().AsNoTracking()
.选择(m=>新电影{
movie\u id=m.movie\u id,
title=m.title,
description=m.description
});
如果(!string.IsNullOrWhiteSpace(vm.Search)){
query=query.Where(m=>m.title.Contains(vm.Search));
}
var moviesTask=query.Skip(_pageSize*(vm.Page-1)).Take(_pageSize.toListSync();
var countTask=query.CountAsync();
vm.Movies=等待Movies任务;
vm.PageSize=\u PageSize;
vm.TotalItemCount=等待计数任务;
返回视图(vm);
}
我怀疑你不是在寻找10毫秒的性能调整。相反,请关注查询计划

你应该尝试的事情

  • .OrderBy(m=>m.title)
    添加到
    query
  • 添加更多索引
  • 清除查询缓存
  • 要检查的东西

  • 您是否准确地进行了基准测试?是8秒的JITer加上2秒的实际运行吗
  • 有没有奇怪的HTTP系统,比如代理
  • DNS
  • 您是在发布模式还是调试模式下运行

  • 听起来你的问题与你的要求无关。EF中存在性能问题。你应该解决这个问题。尝试清除查询缓存。我想知道为什么必须调用
    \u movieRepository.GetQueryable()
    。除非你的_movieRepository还不是一个
    IQueryable
    ,否则这看起来是一个冗余。你能发布它的定义吗?如果它是一个
    IEnumerable
    ,那么这就是你的问题:它总体上发生在内存中dataset@Tseng_movieRepository是存储库模式中的存储库。GetQueryable是我自己创建的一个函数,它返回电影实体的IQueryable。当我进一步研究这个函数时,它将在movieRepository中得到它自己的函数。而不是把这些逻辑直接放在我的控制器里。