asp.net - Odata [EnableQuery] 属性使 EF Core 在高请求量时崩溃
问题描述
在我的 Odata 控制器中,我使用 [EnableQuery(EnsureStableOrdering = false)]。稳定的排序是因为我在我的代码中需要一些自定义订单。上述问题中的示例
但是,问题通常与 [EnableQuery] 属性有关。当我在高负载的控制器中具有此属性时,这意味着在同一端点上一分钟内有超过 150 个请求,我得到很多以下异常:
"System.InvalidOperationException","Message":"在前一个操作完成之前,在此上下文上启动了第二个操作。这通常是由不同的线程同时使用相同的 DbContext 实例引起的。"
我使用了测试工具,它将这种请求发送到我的端点(结果是一分钟内大约有 240 个请求,每个请求之间有 1 秒的延迟)并且大多数请求成功,比如大约 85% - 90%,但是失败了请求得到上述异常。
我需要一些时间来弄清楚发生了什么,但是当我删除 [EnableQuery] 属性时,一切都很好。任何级别的请求量都不例外。
这里有一些代码:
public class OfficeDtoController : ODataController
{
private readonly IOfficesService _officesService;
public OfficeDtoController(IOfficesService officesService)
{
_officesService = officesService;
}
[HttpGet]
[EnableQuery(EnsureStableOrdering = false)]
public IActionResult GetOfficeDto(ODataQueryOptions<OfficeDto> queryOptions, Guid? id = null, string sortColumn = "", string sortOrder = "", int? top = null, int? skip = null)
{
IQueryable<OfficeDto> officeDto = _officesService.GetOffices(id, sortColumn, sortOrder, top, skip);
return Ok(officeDto);
}
}
public IQueryable<OfficeDto> GetOffices(Guid? id, string sortColumn, string sortOrder, int? top, int? skip)
{
IQueryable<Office> query = dbSet;
query = query
.Where(z => !z.Deleted);
var list = query.Select(x =>
new OfficeDto()
{
Id = x.Id,
ZipCode = x.ZipCode,
Active = x..Active,
Employees = x.XrefOfficesEmployees
.OrderBy(y => y.Order)
.Select(y => new IdAndName()
{
Value = y.EmployeeId,
Text = y.Employee.FirstName + " " + y.Employee.LastName,
Order = y.Order
})
});
switch (sortColumn)
{
case "employees":
if (sortOrder == "desc")
{
officeDto = officeDto.OrderByDescending(b => b.Employees.Select(a => a.Text).FirstOrDefault( ));
}
else
{
officeDto = officeDto.OrderBy(b => b.Employees.Select(a => a.Text).FirstOrDefault( ));
}
}
return list;
}
这是示例网址:
api/OfficeDto?$count=true&$top=20&$skip=0&$select=id,zipcode,employees&$filter=(active eq true)
可能 EF Core 和 Odata 之间的通信存在问题。
我在 NET 5 和以下 NuGet 上使用 ASP.NET Wen API:
- Microsoft.AspNetCore.OData 7.5.4
- Microsoft.Data.OData 5.8.4
- Microsoft.OData.Core 7.8.1
- Microsoft.EntityFrameworkCore 5.0.2
编辑:
对于那些询问 DI 的人:
services.AddDbContext<MyContext>( );
services.AddTransient<IOffcesService, OfficesService>( );
但是我尝试初始化控制器中的所有内容(数据库上下文和业务服务),因为起初我的建议是关于 DI,但它没有帮助。
解决方案
推荐阅读
- oracle - (Oracle)如何在横纵坐标的表格中选择数据?
- node.js - 在我的服务器中包含所有请求的大量小文件或一个大文件在性能方面更好吗?
- javascript - 隐藏div点击外面
- ios - 无法将“Result”类型的值转换为预期的参数类型“EmailContentData”
- apache-spark - 使用逗号分隔符将一列拆分为 Spark DataFrame 中的多列
- php - htaccess 中的 url 友好重定向问题
- c# - 实体框架核心不包含 ToListAsync 时,但包含 FirstOrDefaultAsync
- asp.net-core - IIS 中的“维护中”视图,同时停止/启动 .net 核心应用程序
- jira - 如何设置服务帐户以使用 JIRA API?
- docker - 在 Docker 中的 Docker 中预拉图像 (dind)