C# 使用实体框架处理的时间过长

C# 使用实体框架处理的时间过长,c#,entity-framework-core,C#,Entity Framework Core,我很难确定为什么运行以下程序需要700毫秒 [Fact] public async Task Get_proyecto_all_sucess() { //Arrange var expectedItems = 4; var proyectoContext = new MultiLangDbContext(_dbOptions); var proyectoServ = new ProyectoService(

我很难确定为什么运行以下程序需要700毫秒

    [Fact]
    public async Task Get_proyecto_all_sucess()
    {
        //Arrange
        var expectedItems = 4;

        var proyectoContext = new MultiLangDbContext(_dbOptions);
        var proyectoServ = new ProyectoService(proyectoContext);

        //Act
        var proyectoController = new ProyectoController(proyectoServ);
        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();
        var actionResult = await proyectoController.AllAsync();
        stopwatch.Stop();
        Debug.WriteLine($"All: took {stopwatch.ElapsedMilliseconds}");
        var result = actionResult as ObjectResult;

        //Assert
        var returned = Assert.IsType<List<Proyecto>>(result.Value);
        returned.Count.Should().Be(expectedItems);
    }

    //here the function thats demanding that amount of time
    [HttpGet]
    [Route("All")]
    [ProducesResponseType((int)HttpStatusCode.BadRequest)]
    public virtual async Task<IActionResult> AllAsync()
    {
        var model = await _baseServ.GetTodosAsync();

        return Ok(model);
    }


    //here the service thats being called
    public virtual async Task<IEnumerable<T>> GetTodosAsync() => await _ctx.Set<T>().Where(x => !x._deleted).ToListAsync();

   //here the sql code being generated by entity
   SELECT [p].[Id], [p].[Nombre], [p].[_deleted]
   FROM [Proyectos] AS [p]
   WHERE [p].[_deleted] <> CAST(1 AS bit)
    [Fact]
    public async Task Get_proyecto_items_success()
    {
        //Arrange
        var pageSize = 3;
        var pageIndex = 0;

        var expectedItemsInPage = 3;
        var expectedTotalItems = 4;

        var proyectoContext = new MultiLangDbContext(_dbOptions);
        var proyectoServ = new ProyectoService(proyectoContext);

        //Act
        var proyectoController = new ProyectoController(proyectoServ);
        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();
        var actionResult = await proyectoController.PagedAsync(pageSize, pageIndex);
        stopwatch.Stop();
        Debug.WriteLine($"Items: took {stopwatch.ElapsedMilliseconds}");
        var result = actionResult as ObjectResult;

        //Assert
        //Assert.IsType<PaginatedItemsViewModel<Proyecto>>(result.Value);
        result.Value.Should().BeOfType<PaginatedItemsViewModel<Proyecto>>();
        //var page = Assert.IsAssignableFrom<PaginatedItemsViewModel<Proyecto>>(result.Value);
        var page = result.Value.Should().BeAssignableTo<PaginatedItemsViewModel<Proyecto>>("Es el tipo de retorno").Which;
        page.Count.Should().Be(expectedTotalItems, "Por que es la cantidad de items no borrados");
        page.PageIndex.Should().Be(pageIndex, $"por que el indice pasado es {pageIndex}");
        page.PageSize.Should().Be(pageSize, $"por que el tamaño que le indicamos es de {pageSize}");
        page.Data.Count().Should().Be(expectedItemsInPage, $"por que el tamaño maximo es de {expectedTotalItems}");
    }

    //here the controller for this one
    [HttpGet]
    [Route("items")]
    [ProducesResponseType(typeof(PaginatedItemsViewModel<Proyecto>), (int)HttpStatusCode.OK)]
    [ProducesResponseType(typeof(IEnumerable<Proyecto>), (int)HttpStatusCode.OK)]
    [ProducesResponseType((int)HttpStatusCode.BadRequest)]
    public virtual async Task<IActionResult> PagedAsync([FromQuery] int pageSize = 10, [FromQuery] int pageIndex = 0, string ids = null)
    {
        if (!string.IsNullOrEmpty(ids))
        {
            var items = await _proyectoServ.GetByIdsAsync(ids);

            if (!items.Any())
            {
                return BadRequest("ids value invalid. Must be comma-separated list of numbers");
            }

            return Ok(items);
        }

        var totalItems = await _proyectoServ.GetTotal();

        var itemsOnPage = await _proyectoServ.GetPaged(pageSize, pageIndex, x => x.Nombre);

        var model = new PaginatedItemsViewModel<Proyecto>(pageIndex, pageSize, totalItems, itemsOnPage);

        return Ok(model);
    }
 
    //here the function being called    
    public async Task<IEnumerable<T>> GetPaged<TKey>(int pageSize = 10, int pageNumber = 0, System.Func<T, TKey> order = null)
    {
        //Si hay problemas con esto particularmente hay que ver si hay una mejor manera de implementar el orden y que sea compatible con Async
        if (order != null)
            return 
                _ctx.Set<T>()
                    .OrderBy(order)
                    .Where(x => !x._deleted)
                    .Skip(pageSize * pageNumber)
                    .Take(pageSize)
                    .ToList();
        else
            return await
                _ctx.Set<T>()
                    .Where(x => !x._deleted)
                    .Skip(pageSize * pageNumber)
                    .Take(pageSize)
                    .ToListAsync();
    }

 //here the sql being generated
 SELECT [p].[Id], [p].[Nombre], [p].[_deleted]
 FROM [Proyectos] AS [p]
[事实]
公共异步任务Get_proyecto_all_success()
{
//安排
var-expectedItems=4;
var proyectoContext=新的MultiLangDbContext(_dbOptions);
var proyectoServ=新的ProyectoService(proyectoContext);
//表演
var proyectoController=新的proyectoController(proyectoServ);
秒表秒表=新秒表();
秒表。开始();
var actionResult=await proyectoController.AllAsync();
秒表;
Debug.WriteLine($“All:take{stopwatch.elapsedmillesons}”);
var结果=作为ObjectResult的actionResult;
//断言
返回的var=Assert.IsType(result.Value);
返回的.Count.Should().Be(expectedItems);
}
//这里的函数需要这样的时间
[HttpGet]
[路线(“全部”)]
[产品响应类型((int)HttpStatusCode.BadRequest)]
公共虚拟异步任务AllAsync()
{
var model=await_baseServ.GetTodosAsync();
返回Ok(型号);
}
//这里是被呼叫的服务
公共虚拟异步任务GetTodosAsync()=>await _ctx.Set()。其中(x=>!x._已删除)。ToListAsync();
//这里是实体生成的sql代码
选择[p].[Id],[p].[Nombre],[p].[U已删除]
从[Proyectos]AS[p]
其中[p].[U已删除]强制转换(1位)
我还有一个类似的测试,需要40毫秒,如下所示

    [Fact]
    public async Task Get_proyecto_all_sucess()
    {
        //Arrange
        var expectedItems = 4;

        var proyectoContext = new MultiLangDbContext(_dbOptions);
        var proyectoServ = new ProyectoService(proyectoContext);

        //Act
        var proyectoController = new ProyectoController(proyectoServ);
        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();
        var actionResult = await proyectoController.AllAsync();
        stopwatch.Stop();
        Debug.WriteLine($"All: took {stopwatch.ElapsedMilliseconds}");
        var result = actionResult as ObjectResult;

        //Assert
        var returned = Assert.IsType<List<Proyecto>>(result.Value);
        returned.Count.Should().Be(expectedItems);
    }

    //here the function thats demanding that amount of time
    [HttpGet]
    [Route("All")]
    [ProducesResponseType((int)HttpStatusCode.BadRequest)]
    public virtual async Task<IActionResult> AllAsync()
    {
        var model = await _baseServ.GetTodosAsync();

        return Ok(model);
    }


    //here the service thats being called
    public virtual async Task<IEnumerable<T>> GetTodosAsync() => await _ctx.Set<T>().Where(x => !x._deleted).ToListAsync();

   //here the sql code being generated by entity
   SELECT [p].[Id], [p].[Nombre], [p].[_deleted]
   FROM [Proyectos] AS [p]
   WHERE [p].[_deleted] <> CAST(1 AS bit)
    [Fact]
    public async Task Get_proyecto_items_success()
    {
        //Arrange
        var pageSize = 3;
        var pageIndex = 0;

        var expectedItemsInPage = 3;
        var expectedTotalItems = 4;

        var proyectoContext = new MultiLangDbContext(_dbOptions);
        var proyectoServ = new ProyectoService(proyectoContext);

        //Act
        var proyectoController = new ProyectoController(proyectoServ);
        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();
        var actionResult = await proyectoController.PagedAsync(pageSize, pageIndex);
        stopwatch.Stop();
        Debug.WriteLine($"Items: took {stopwatch.ElapsedMilliseconds}");
        var result = actionResult as ObjectResult;

        //Assert
        //Assert.IsType<PaginatedItemsViewModel<Proyecto>>(result.Value);
        result.Value.Should().BeOfType<PaginatedItemsViewModel<Proyecto>>();
        //var page = Assert.IsAssignableFrom<PaginatedItemsViewModel<Proyecto>>(result.Value);
        var page = result.Value.Should().BeAssignableTo<PaginatedItemsViewModel<Proyecto>>("Es el tipo de retorno").Which;
        page.Count.Should().Be(expectedTotalItems, "Por que es la cantidad de items no borrados");
        page.PageIndex.Should().Be(pageIndex, $"por que el indice pasado es {pageIndex}");
        page.PageSize.Should().Be(pageSize, $"por que el tamaño que le indicamos es de {pageSize}");
        page.Data.Count().Should().Be(expectedItemsInPage, $"por que el tamaño maximo es de {expectedTotalItems}");
    }

    //here the controller for this one
    [HttpGet]
    [Route("items")]
    [ProducesResponseType(typeof(PaginatedItemsViewModel<Proyecto>), (int)HttpStatusCode.OK)]
    [ProducesResponseType(typeof(IEnumerable<Proyecto>), (int)HttpStatusCode.OK)]
    [ProducesResponseType((int)HttpStatusCode.BadRequest)]
    public virtual async Task<IActionResult> PagedAsync([FromQuery] int pageSize = 10, [FromQuery] int pageIndex = 0, string ids = null)
    {
        if (!string.IsNullOrEmpty(ids))
        {
            var items = await _proyectoServ.GetByIdsAsync(ids);

            if (!items.Any())
            {
                return BadRequest("ids value invalid. Must be comma-separated list of numbers");
            }

            return Ok(items);
        }

        var totalItems = await _proyectoServ.GetTotal();

        var itemsOnPage = await _proyectoServ.GetPaged(pageSize, pageIndex, x => x.Nombre);

        var model = new PaginatedItemsViewModel<Proyecto>(pageIndex, pageSize, totalItems, itemsOnPage);

        return Ok(model);
    }
 
    //here the function being called    
    public async Task<IEnumerable<T>> GetPaged<TKey>(int pageSize = 10, int pageNumber = 0, System.Func<T, TKey> order = null)
    {
        //Si hay problemas con esto particularmente hay que ver si hay una mejor manera de implementar el orden y que sea compatible con Async
        if (order != null)
            return 
                _ctx.Set<T>()
                    .OrderBy(order)
                    .Where(x => !x._deleted)
                    .Skip(pageSize * pageNumber)
                    .Take(pageSize)
                    .ToList();
        else
            return await
                _ctx.Set<T>()
                    .Where(x => !x._deleted)
                    .Skip(pageSize * pageNumber)
                    .Take(pageSize)
                    .ToListAsync();
    }

 //here the sql being generated
 SELECT [p].[Id], [p].[Nombre], [p].[_deleted]
 FROM [Proyectos] AS [p]
[事实]
公共异步任务获取\u项目\u项目成功()
{
//安排
var pageSize=3;
var pageIndex=0;
var expectedItemsInPage=3;
var expectedTotalItems=4;
var proyectoContext=新的MultiLangDbContext(_dbOptions);
var proyectoServ=新的ProyectoService(proyectoContext);
//表演
var proyectoController=新的proyectoController(proyectoServ);
秒表秒表=新秒表();
秒表。开始();
var actionResult=await proyectoController.PagedAsync(页面大小、页面索引);
秒表;
Debug.WriteLine($“Items:take{stopwatch.elapsedmillesons}”);
var结果=作为ObjectResult的actionResult;
//断言
//Assert.IsType(result.Value);
result.Value.Should().BeOfType();
//var page=Assert.IsAssignableFrom(result.Value);
var page=result.Value.Should();
page.Count.Should().Be(预期总数,“项目编号为borrados的项目数量”);
PageIndex.Should().Be(PageIndex,$“por que el indice pasado es{PageIndex}”);
page.PageSize.Should().Be(PageSize,$“por que el-tamaño que le indicatomos es de{PageSize}”);
page.Data.Count().Should().Be(expectedItemsInPage,$“por que el-tamaño maximo de{expectedTotalItems}”);
}
//这是这个的控制器
[HttpGet]
[路线(“项目”)]
[产品响应类型(typeof(PaginatedItemsViewModel),(int)HttpStatusCode.OK)]
[产品响应类型(typeof(IEnumerable),(int)HttpStatusCode.OK)]
[产品响应类型((int)HttpStatusCode.BadRequest)]
公共虚拟异步任务PagedAsync([FromQuery]int pageSize=10,[FromQuery]int pageIndex=0,字符串ID=null)
{
如果(!string.IsNullOrEmpty(ids))
{
var items=await _proyectoServ.getbyidsaync(ids);
如果(!items.Any())
{
返回BadRequest(“ids值无效。必须是逗号分隔的数字列表”);
}
返回Ok(项目);
}
var totalItems=await_proyectoServ.GetTotal();
var itemsOnPage=wait _proyectoServ.GetPaged(pageSize,pageIndex,x=>x.Nombre);
var模型=新的PaginatedItemsViewModel(pageIndex、pageSize、totalItems、itemsOnPage);
返回Ok(型号);
}
//这里是正在调用的函数
公共异步任务GetPaged(int pageSize=10,int pageNumber=0,System.Func order=null)
{
//这是一个问题,特别是在不同步的情况下,实现了与海洋兼容的环境
如果(订单!=null)
返回
_ctx.Set()
.OrderBy(订单)
。其中(x=>!x.。\u已删除)
.跳过(页面大小*页码)
.Take(页面大小)
.ToList();
其他的
返回等待
_ctx.Set()
。其中(x=>!x.。\u已删除)
.跳过(页面大小*页码)
.Take(页面大小)
.ToListAsync();
}
//这里是正在生成的sql
选择[p].[Id],[p].[Nombre],[p].[U已删除]
从[Proyectos]AS[p]
到目前为止,我尝试了很多方法,看看是否可以使700毫秒(内存sql)/1.1秒(普通sql)变为700毫秒,但我做不到,这就是我尝试的:

  • 我的迁移没有设置最大字符数,因此它们是使用nvharchar(max)生成的 现在Id是nvarchar(50),Nombre是nvarchar(60),而_deleted是bit。没什么变化
  • 在成为泛型函数之前,它被称为像_ctx.Proyectos.Where(x=>!x.deleted).toListSync(),这也没有改变什么
  • 我尝试了内存Sql和普通Sql,正常运行的需要40毫秒/80毫秒,而不正常运行的需要700毫秒/1.1秒
  • 这两个SQL都是在ManagementStudio中运行的,处理它们所需的时间几乎为零
  • 我试着一个接一个地运行测试,看看这是否是问题所在,这也是一个否定的答案
老实说,我已经没有选择了,我唯一能看到的是进行sql调用,但我更喜欢这样简单的东西,以便能够使用ORM。有什么想法吗

编辑:这是模拟的