C# SQL请求执行后控制器操作挂起数秒

C# SQL请求执行后控制器操作挂起数秒,c#,asp.net-core,entity-framework-core,ef-core-2.0,C#,Asp.net Core,Entity Framework Core,Ef Core 2.0,我面临着一个我无法解决的问题。我在ASP.NET核心控制器中有一个操作,在执行SQL请求后,它似乎会挂起一段时间 以下是代码示例: [HttpGet(“slow/action/{scopeType}/{scopeId}”)] 公共异步任务MySlowAction(ScopeType ScopeType,Guid scopeId) { 尝试 { IEnumerable orders=this.DbContext.SalesOrders .Include(so=>so.Store) 。然后包括(s=

我面临着一个我无法解决的问题。我在ASP.NET核心控制器中有一个操作,在执行SQL请求后,它似乎会挂起一段时间

以下是代码示例:

[HttpGet(“slow/action/{scopeType}/{scopeId}”)]
公共异步任务MySlowAction(ScopeType ScopeType,Guid scopeId)
{
尝试
{
IEnumerable orders=this.DbContext.SalesOrders
.Include(so=>so.Store)
。然后包括(s=>s区)
.Include(so=>so.OrderingPlatform)
.Include(so=>so.Items)
.然后包括(soi=>soi.项目);
开关(范围类型)
{
案例范围类型。区域:
Region Region=等待this.DbContext.Regions
.FirstOrDefaultAsync(r=>r.Id==scopeId);
如果(区域==null)
{
this.ModelState.AddModelError(nameof(scopeId),$”未能找到具有指定id“{scopeId}”的区域);
返回此.BadRequest(此.ModelState);
}
orders=orders.Where(so=>so.Store.District.RegionId==region.Id);
打破
违约:
this.ModelState.AddModelError(nameof(scopeType),$“不支持指定的作用域类型{scopeType}”);
返回此.BadRequest(此.ModelState);
}
订单=订单
.Where(so=>
so.State==SalesOrderState.Prepared | | so.State==SalesOrderState.Completed
&&so.Destination==SalesOrderDestination.Customer
&&so.DueDate.Date==DateTime.UtcNow.Date
)
.ToList();
ScopeStatisticsInfo stats=新ScopeStatisticsInfo()
{
ScopeType=ScopeType,
ScopedId=scopeId,
TotalTickets=orders.Count(),
TotalSales=订单。SelectMany(so=>so.Items)。Sum(soi=>soi.Quantity),
TotalSales营业额=orders.Sum(so=>so.Total),
AverageTicket=orders.Any()?orders.Average(so=>so.Total):(十进制?)null,
AverageSalesticket=orders.Any()?orders.Average(so=>so.Items.Sum(soi=>soi.Quantity)):(double?)null,
顶销=订单
.SelectMany(so=>so.Items)
.GroupBy(so=>so.ProductId)
.OrderByDescending(g=>g.Sum(soi=>soi.Quantity))
.采取(3)
.Select(g=>newproductsalesinfo()
{
Product=this.Mapper.Map(this.DbContext.Products.First(p=>p.Id==g.First().ProductId)),
销售=总金额(soi=>soi.数量)
})
托利斯先生()
};
返回这个。Ok(统计);
}
捕获(例外情况除外)
{
this.Logger?.LogError($“检索id为{scopeId}的类型{scopeType}的作用域的统计信息时出错:{Environment.NewLine}{ex.ToString()}”);
返回此.StatusCode((int)HttpStatusCode.InternalServerError);
}
}
在我的用例中,该操作似乎挂起在对.ToList()方法的调用和新ScopeStatisticsInfo的实例化之间


来自.ToList()方法的底层SQL请求只需800毫秒即可执行,在我的测试用例中,不返回任何实体,列表为空。但是,在点击“new ScopeStatisticsInfo”之前,进程将挂起几秒钟,一些未知线程将退出。整个动作大约需要30/40秒。以下是调试输出:

Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 OPTIONS http://foo.bar.com/api/v1/dashboard/slow/action/region/ceffa31f-ce09-4ed8-8717-1dbc73d968b7?ui-culture=fr  
Microsoft.AspNetCore.Cors.Infrastructure.CorsService:Information: CORS policy execution successful.
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 20.8107ms 204 
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://foo.bar.com/api/v1/dashboard/slow/action/region/ceffa31f-ce09-4ed8-8717-1dbc73d968b7?ui-culture=fr  
Microsoft.AspNetCore.Cors.Infrastructure.CorsService:Information: CORS policy execution successful.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Route matched with {area = "api", action = "MySlowAction", controller = "Dashboard"}. Executing action Foo.Bar.Controllers.DashboardController.MySlowAction (Foo.Bar)
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization was successful.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executing action method Foo.Bar.Controllers.DashboardController.MySlowAction (Foo.Bar) with arguments (Region, ceffa31f-ce09-4ed8-8717-1dbc73d968b7) - Validation state: Valid
Microsoft.EntityFrameworkCore.Infrastructure:Information: Entity Framework Core 2.2.2-servicing-10034 initialized 'ApplicationDbContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: None
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (0ms) [Parameters=[@__scopeId_0='?' (DbType = Guid)], CommandType='Text', CommandTimeout='30']
SELECT TOP(1) [r].[Id], [r].[CreatedAt], [r].[Currency], [r].[DescriptionKey], [r].[IsDeleted], [r].[IsoCode], [r].[Label], [r].[LastModified], [r].[NameKey], [r].[RowVersion]
FROM [Regions] AS [r]
WHERE ([r].[IsDeleted] = 0) AND ([r].[Id] = @__scopeId_0)
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (0ms) [Parameters=[@__scopeId_0='?' (DbType = Guid)], CommandType='Text', CommandTimeout='30']
SELECT TOP(1) [r].[Id], [r].[CreatedAt], [r].[Currency], [r].[DescriptionKey], [r].[IsDeleted], [r].[IsoCode], [r].[Label], [r].[LastModified], [r].[NameKey], [r].[RowVersion]
FROM [Regions] AS [r]
WHERE ([r].[IsDeleted] = 0) AND ([r].[Id] = @__scopeId_0)
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (243ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [so].[Id], [so].[Alias], [so].[Comments], [so].[ContactPhoneNumberId], [so].[ContactPhoneNumberSnapshot], [so].[CreatedAt], [so].[Currency], [so].[CustomerEmailSnapshot], [so].[CustomerId], [so].[DeliveryAddressId], [so].[DeliveryAddressSnapshot], [so].[Destination], [so].[Dispatcher], [so].[DueDate], [so].[InvoiceAddressId], [so].[InvoiceAddressSnapshot], [so].[LastModified], [so].[OrderTypeId], [so].[OrderingPlatformId], [so].[PreparationTime], [so].[PreparedAt], [so].[RowVersion], [so].[Sequence], [so].[State], [so].[StoreId], [so].[SubTotal], [so].[TimeSlotId], [so].[Total], [so].[TotalDiscounts], [so].[TotalFees], [so].[TotalImplicitDiscounts], [so].[TotalTaxes], [so.OrderingPlatform].[Id], [so.OrderingPlatform].[CreatedAt], [so.OrderingPlatform].[DescriptionKey], [so.OrderingPlatform].[Label], [so.OrderingPlatform].[LastModified], [so.OrderingPlatform].[NameKey], [so.OrderingPlatform].[OrderChannelType], [so.OrderingPlatform].[RowVersion], [so.OrderingPlatform].[Spi], [t].[Id], [t].[AddressId], [t].[CreatedAt], [t].[DeliveryProvider], [t].[DescriptionKey], [t].[DistrictId], [t].[Email], [t].[IsDeleted], [t].[Label], [t].[LastModified], [t].[MaximumDeliveryDistance], [t].[MaximumOrderLifetime], [t].[MaximumStackableDeliveries], [t].[MaximumStackableDeliveryDistance], [t].[MaximumStackingInterval], [t].[NameKey], [t].[RowVersion], [t].[SalesOrderDispatcher], [t].[StockId], [t0].[Id], [t0].[CreatedAt], [t0].[DescriptionKey], [t0].[IsDeleted], [t0].[Label], [t0].[LastModified], [t0].[NameKey], [t0].[RegionId], [t0].[RowVersion], [t0].[TimeZoneId]
FROM [SalesOrders] AS [so]
INNER JOIN [Applications] AS [so.OrderingPlatform] ON [so].[OrderingPlatformId] = [so.OrderingPlatform].[Id]
INNER JOIN (
    SELECT [s].[Id], [s].[AddressId], [s].[CreatedAt], [s].[DeliveryProvider], [s].[DescriptionKey], [s].[DistrictId], [s].[Email], [s].[IsDeleted], [s].[Label], [s].[LastModified], [s].[MaximumDeliveryDistance], [s].[MaximumOrderLifetime], [s].[MaximumStackableDeliveries], [s].[MaximumStackableDeliveryDistance], [s].[MaximumStackingInterval], [s].[NameKey], [s].[RowVersion], [s].[SalesOrderDispatcher], [s].[StockId]
    FROM [Stores] AS [s]
    WHERE [s].[IsDeleted] = 0
) AS [t] ON [so].[StoreId] = [t].[Id]
INNER JOIN (
    SELECT [d].[Id], [d].[CreatedAt], [d].[DescriptionKey], [d].[IsDeleted], [d].[Label], [d].[LastModified], [d].[NameKey], [d].[RegionId], [d].[RowVersion], [d].[TimeZoneId]
    FROM [Districts] AS [d]
    WHERE [d].[IsDeleted] = 0
) AS [t0] ON [t].[DistrictId] = [t0].[Id]
ORDER BY [so].[Id]
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (183ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [so.Items].[Id], [so.Items].[Comments], [so.Items].[CompositionItemType], [so.Items].[CreatedAt], [so.Items].[DisplayOrder], [so.Items].[ImplicitDiscount], [so.Items].[IsCustomized], [so.Items].[LastModified], [so.Items].[OrderId], [so.Items].[ParentOrderItemId], [so.Items].[ProductId], [so.Items].[ProductLabel], [so.Items].[ProductPrice], [so.Items].[ProductPriceSpecificationId], [so.Items].[Quantity], [so.Items].[RowVersion], [so.Items].[SubTotal], [so.Items].[Total], [so.Items].[TotalDiscounts], [so.Items].[TotalFees], [so.Items].[TotalTaxes], [so.Items].[VatId], [so.Items].[VatLabel], [so.Items].[VatRate]
FROM [SalesOrderItems] AS [so.Items]
INNER JOIN (
    SELECT DISTINCT [so0].[Id]
    FROM [SalesOrders] AS [so0]
    INNER JOIN [Applications] AS [so.OrderingPlatform0] ON [so0].[OrderingPlatformId] = [so.OrderingPlatform0].[Id]
    INNER JOIN (
        SELECT [s0].*
        FROM [Stores] AS [s0]
        WHERE [s0].[IsDeleted] = 0
    ) AS [t1] ON [so0].[StoreId] = [t1].[Id]
    INNER JOIN (
        SELECT [d0].*
        FROM [Districts] AS [d0]
        WHERE [d0].[IsDeleted] = 0
    ) AS [t2] ON [t1].[DistrictId] = [t2].[Id]
) AS [t3] ON [so.Items].[OrderId] = [t3].[Id]
ORDER BY [t3].[Id], [so.Items].[Id]
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (837ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [so.Items.Items].[Id], [so.Items.Items].[Comments], [so.Items.Items].[CompositionItemType], [so.Items.Items].[CreatedAt], [so.Items.Items].[DisplayOrder], [so.Items.Items].[ImplicitDiscount], [so.Items.Items].[IsCustomized], [so.Items.Items].[LastModified], [so.Items.Items].[OrderId], [so.Items.Items].[ParentOrderItemId], [so.Items.Items].[ProductId], [so.Items.Items].[ProductLabel], [so.Items.Items].[ProductPrice], [so.Items.Items].[ProductPriceSpecificationId], [so.Items.Items].[Quantity], [so.Items.Items].[RowVersion], [so.Items.Items].[SubTotal], [so.Items.Items].[Total], [so.Items.Items].[TotalDiscounts], [so.Items.Items].[TotalFees], [so.Items.Items].[TotalTaxes], [so.Items.Items].[VatId], [so.Items.Items].[VatLabel], [so.Items.Items].[VatRate]
FROM [SalesOrderItems] AS [so.Items.Items]
INNER JOIN (
    SELECT DISTINCT [so.Items0].[Id], [t6].[Id] AS [Id0]
    FROM [SalesOrderItems] AS [so.Items0]
    INNER JOIN (
        SELECT DISTINCT [so1].[Id]
        FROM [SalesOrders] AS [so1]
        INNER JOIN [Applications] AS [so.OrderingPlatform1] ON [so1].[OrderingPlatformId] = [so.OrderingPlatform1].[Id]
        INNER JOIN (
            SELECT [s1].*
            FROM [Stores] AS [s1]
            WHERE [s1].[IsDeleted] = 0
        ) AS [t4] ON [so1].[StoreId] = [t4].[Id]
        INNER JOIN (
            SELECT [d1].*
            FROM [Districts] AS [d1]
            WHERE [d1].[IsDeleted] = 0
        ) AS [t5] ON [t4].[DistrictId] = [t5].[Id]
    ) AS [t6] ON [so.Items0].[OrderId] = [t6].[Id]
) AS [t7] ON [so.Items.Items].[ParentOrderItemId] = [t7].[Id]
ORDER BY [t7].[Id0], [t7].[Id]
Le thread 0x2f7c s'est arrêté avec le code 0 (0x0).
Le thread 0x31a0 s'est arrêté avec le code 0 (0x0).
Le thread 0x2b4c s'est arrêté avec le code 0 (0x0).
Le thread 0x128 s'est arrêté avec le code 0 (0x0).
Le thread 0x333c s'est arrêté avec le code 0 (0x0).
Le thread 0x2ba0 s'est arrêté avec le code 0 (0x0).
Le thread 0x119c s'est arrêté avec le code 0 (0x0).
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [s].[Id], [s].[CreatedAt], [s].[DescriptionKey], [s].[Label], [s].[LastModified], [s].[NameKey], [s].[RowVersion]
FROM [SalesOrderTypes] AS [s]
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (0ms) [Parameters=[@__sourceMember_0='?' (Size = 450)], CommandType='Text', CommandTimeout='30']
SELECT [ls].[Id], [ls].[CreatedAt], [ls].[Key], [ls].[Language], [ls].[LastModified], [ls].[RowVersion], [ls].[Value]
FROM [LocalizedStrings] AS [ls]
WHERE [ls].[Key] = @__sourceMember_0
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (0ms) [Parameters=[@__sourceMember_0='?' (Size = 450)], CommandType='Text', CommandTimeout='30']
SELECT [ls].[Id], [ls].[CreatedAt], [ls].[Key], [ls].[Language], [ls].[LastModified], [ls].[RowVersion], [ls].[Value]
FROM [LocalizedStrings] AS [ls]
WHERE [ls].[Key] = @__sourceMember_0
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (0ms) [Parameters=[@__sourceMember_0='?' (Size = 450)], CommandType='Text', CommandTimeout='30']
SELECT [ls].[Id], [ls].[CreatedAt], [ls].[Key], [ls].[Language], [ls].[LastModified], [ls].[RowVersion], [ls].[Value]
FROM [LocalizedStrings] AS [ls]
WHERE [ls].[Key] = @__sourceMember_0
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (0ms) [Parameters=[@__sourceMember_0='?' (Size = 450)], CommandType='Text', CommandTimeout='30']
SELECT [ls].[Id], [ls].[CreatedAt], [ls].[Key], [ls].[Language], [ls].[LastModified], [ls].[RowVersion], [ls].[Value]
FROM [LocalizedStrings] AS [ls]
WHERE [ls].[Key] = @__sourceMember_0
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (0ms) [Parameters=[@__sourceMember_0='?' (Size = 450)], CommandType='Text', CommandTimeout='30']
SELECT [ls].[Id], [ls].[CreatedAt], [ls].[Key], [ls].[Language], [ls].[LastModified], [ls].[RowVersion], [ls].[Value]
FROM [LocalizedStrings] AS [ls]
WHERE [ls].[Key] = @__sourceMember_0
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (0ms) [Parameters=[@__sourceMember_0='?' (Size = 450)], CommandType='Text', CommandTimeout='30']
SELECT [ls].[Id], [ls].[CreatedAt], [ls].[Key], [ls].[Language], [ls].[LastModified], [ls].[RowVersion], [ls].[Value]
FROM [LocalizedStrings] AS [ls]
WHERE [ls].[Key] = @__sourceMember_0
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (0ms) [Parameters=[@__sourceMember_0='?' (Size = 450)], CommandType='Text', CommandTimeout='30']
SELECT [ls].[Id], [ls].[CreatedAt], [ls].[Key], [ls].[Language], [ls].[LastModified], [ls].[RowVersion], [ls].[Value]
FROM [LocalizedStrings] AS [ls]
WHERE [ls].[Key] = @__sourceMember_0
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (0ms) [Parameters=[@__sourceMember_0='?' (Size = 450)], CommandType='Text', CommandTimeout='30']
SELECT [ls].[Id], [ls].[CreatedAt], [ls].[Key], [ls].[Language], [ls].[LastModified], [ls].[RowVersion], [ls].[Value]
FROM [LocalizedStrings] AS [ls]
WHERE [ls].[Key] = @__sourceMember_0
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action method Foo.Bar.Controllers.DashboardController.MySlowAction (Foo.Bar), returned result Microsoft.AspNetCore.Mvc.OkObjectResult in 36945.1908ms.
Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor:Information: Executing ObjectResult, writing value of type 'Foo.Bar.Controllers.ScopeStatisticsInfo'.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action Foo.Bar.Controllers.DashboardController.MySlowAction (Foo.Bar) in 36960.649ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 36975.0473ms 200 application/json; charset=utf-8
请注意,当SalesOrder表为空时,这种行为不会发生,但当该表中填充了大量条目时,即使请求的结果没有实体,它也会在前面提到的两行代码“中间”挂起一段时间


我完全不知道发生了什么,有人知道为什么在继续之前,即使没有具体化任何实体,操作也会像这样挂起吗?

我不知道原因,但我找到了解决方案。将“订单”上的操作拆分为两个序列,一个使用IQueryable,第二个仅用于收集列表,这在处理方面确实有所改进:

IQueryable ordersQuery=this.DbContext.SalesOrders
.Include(so=>so.Store)
。然后包括(s=>s区)
.Include(so=>so.OrderingPlatform)
.Include(so=>so.Items)
.然后包括(soi=>soi.项目);
开关(范围类型)
{
案例范围类型。区域:
Region Region=等待this.DbContext.Regions
.FirstOrDefaultAsync(r=>r.Id==scopeId);
如果(区域==null)
{
this.ModelState.AddModelError(nameof(scopeId),$”未能找到具有指定id“{scopeId}”的区域);
返回此.BadRequest(此.ModelState);
}
ordersQuery=ordersQuery.Where(so=>so.Store.District.RegionId==region.Id);
打破
违约:
this.ModelState.AddModelError(nameof(scopeType),$“不支持指定的作用域类型{scopeType}”);
返回此.BadRequest(此.ModelState);
}
ordersQuery=ordersQuery
.Where(so=>
so.State==SalesOrderState.Prepared | | so.State==SalesOrderState.Completed
&&so.Destination==SalesOrderDestination.Customer
&&so.DueDate.Date==DateTime.UtcNow.Date
);
List orders=wait ordersQuery.ToListAsync();
对于相同的用例,操作需要几毫秒,而不是30/40秒:

Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action Foo.Bar.Controllers.DashboardController.MySlowAction (Foo.Bar) in 269.9177ms

我不知道原因,但我找到了解决办法。将“订单”上的操作拆分为两个序列,一个使用IQueryable,第二个仅用于收集列表,这在处理方面确实有所改进:

IQueryable ordersQuery=this.DbContext.SalesOrders
.Include(so=>so.Store)
。然后包括(s=>s区)
.Include(so=>so.OrderingPlatform)
.Include(so=>so.Items)
塞尼夫人