首页 > 解决方案 > 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:

编辑:

对于那些询问 DI 的人:

    services.AddDbContext<MyContext>( );
    services.AddTransient<IOffcesService, OfficesService>( );

但是我尝试初始化控制器中的所有内容(数据库上下文和业务服务),因为起初我的建议是关于 DI,但它没有帮助。

标签: asp.netasp.net-coreentity-framework-coreodata

解决方案


推荐阅读