C# 使用实体框架处理的时间过长
我很难确定为什么运行以下程序需要700毫秒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(
[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中运行的,处理它们所需的时间几乎为零
- 我试着一个接一个地运行测试,看看这是否是问题所在,这也是一个否定的答案