.NET Core DbContext阻止后续请求

时间:2019-10-29 18:28:29

标签: .net-core

我们有一个用.Net Core(当前为v2.2)编写的Web应用程序,并且以Angular作为前端。 如果我在后端对一个路由进行ajax调用,这反过来又打开了一个dbcontext来执行查询,那么我们将遇到对其他任何路由的所有后续ajax调用被阻塞,直到查询第一个控制器路由已经完成了。 (不,它不是SQL Server中的DB Lock。它具有不同的表)。

第一条路线中的代码示例(出于示例目的,该过程需要20秒):

public IActionResult GetBusinessesByNaceAndAmount(int take)
{
    using (ConsumentContext consumentContext = new ConsumentContext())
    {
        var data = consumentContext.Businesses.AsNoTracking().Where(b => b.Established_date != null).GroupBy(b => new { Code = b.Business_code.Substring(0, 2) }).Select(b => new
        {
            BusinessName = b.First().Business_code.Substring(0, 2),
            Businesses = b.Where(bl => bl.Established_date != null).OrderBy(bl => bl.Established_date).Select(bl => new { BusinessName = bl.Name, Amount = 10 }).Take(10).ToList(),
        }).Take(take).ToList();

        return Ok(data );
    }
}

然后,我在一毫秒后又在前端执行另一个调用:

public IActionResult GetCustomers()
{
    using (ConsumentContext consumentContext = new ConsumentContext())
    {
        var customers = consumentContext.Customers.AsNoTracking().Take(5).ToList();
        return Ok(customers);
    }
}

即使第二个端点的查询仅花费几毫秒,它的TTFB仍保持到第一个端点完成。

我不知道它是否与它有任何关系,但是我们的后端当前正在linux环境(Docker容器)中运行,并且正在通过TCP / IP与我们的MSSQL服务器进行通信(是的,它被锁定在防火墙)。

1 个答案:

答案 0 :(得分:1)

您的问题似乎是服务器可用线程不足以处理操作,或者在Angular应用程序中您不是同时进行API调用而是按顺序进行。

要释放长时间运行的DB调用中的线程,您可以尝试将第一个操作更改为async操作,以便不冻结线程,例如

public async Task<IActionResult> GetBusinessesByNaceAndAmount(int take, CancellationToken token)
{
    using (ConsumentContext consumentContext = new ConsumentContext())
    {
        var data = await consumentContext.Businesses
            .AsNoTracking()
            .Where(b => b.Established_date != null)
            .GroupBy(b => new { Code = b.Business_code.Substring(0, 2) })
            .Select(b => new
            {
                BusinessName = b.First().Business_code.Substring(0, 2),
                Businesses = b.Where(bl => bl.Established_date != null)
                    .OrderBy(bl => bl.Established_date)
                    .Select(bl => new { BusinessName = bl.Name, Amount = 10})
                    .Take(10).ToList(),
            })
            .Take(take)
            .ToListAsync(token);

        return Ok(data);
    }
}

如果您的服务器用尽了线程来处理该操作,这可能会有所帮助。

您还可以验证您的Angular代码。如果您的应用程序正在等待第一次API调用的结果,那么上面的代码将无济于事-您应该同时进行所有调用。