EF核心和大流量导致最大池大小达到错误

Vít*_*ral 8 c# asp.net asp.net-web-api entity-framework-core .net-core

我们使用ASP.NET Entity Framework Core在我们的Web API应用程序中查询我们的MSSQL数据库.有时,当我们有大量流量时,查询到DB会以此错误结束:

超时已过期.从池中获取连接之前经过的超时时间.这可能是因为所有池连接都在使用中并且达到了最大池大小.

我想知道我们的使用DbContext和查询模式是否正确或者我是否缺少某些使用/ dispose模式和错误是由于某些内存泄漏引起的(在我读过一些研究之后我不应该使用因为生命周期由框架管理) .我正在关注文件 ......

我的connectionString:

"myConnection": "Server=xxx;Database=xxx;user id=xxx;password=xxx;Max Pool Size=200;Timeout=200;"
Run Code Online (Sandbox Code Playgroud)

我的Startup.cs

public void ConfigureServices(IServiceCollection services)
    {
    .....
    // scoped context            
    services.AddDbContext<MyDbContext>(
            options => options.UseSqlServer(this.Configuration.GetConnectionString("myConnection")));
    }
Run Code Online (Sandbox Code Playgroud)

然后在控制器中我通过依赖注入使用了dbcontext:

public class MyController : Controller
   public MyController (MyDbContext context)
    {
        this.Context = context;            
    }

    public ActionResult Get(int id)
    {
        // querying
        return this.Context.tRealty.Where(x=>x.id == id).FirstOrDefault();
    }
Run Code Online (Sandbox Code Playgroud)

我应该使用类似的东西:

using (var context = this.Context)
        {
            return this.Context.tRealty.Where(x => x.id == id).FirstOrDefault();
        }
Run Code Online (Sandbox Code Playgroud)

但我认为当我使用依赖注入时,这是一种糟糕的模式DbContext.

Vít*_*ral 7

我认为问题是由将数据库上下文查询中的对象存储到内存缓存中引起的.我有一个大的LINQ查询到数据库上下文,里面有一些其他子查询.我调用FirstOrDefault()主查询结束但不在子查询.控制器很好用它,它默认实现查询.

 return this.Context.tRealty.AsNoTracking().Where(
                x => x.Id == id && x.RealtyProcess == RealtyProcess.Visible).Select(
                s => new
                { .....

// subquery
videos = s.TVideo.Where(video => video.RealtyId == id && video.IsPublicOnYouTube).
                        Select(video => video.YouTubeId).ToList()), // missing ToList()
.....
 }).FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

并且存在问题 - 子查询在存储到内存缓存中时保持与数据库上下文的连接.当我实现Redis分布式缓存时,它首先失败了一些奇怪的错误.当我写ToList()FirstOrDefault()我的所有子查询时,它会有所帮助,因为分布式缓存需要物化对象.

现在我明确地实现了所有查询,并且没有达到最大池大小错误.因此,当存储的对象从数据库上下文查询到内存缓存时必须小心.需要实现所有查询以避免在内存中的某处保持连接.

  • 哎呀,就打这个。这是一个SQL查询来标识池的操作者:https://gist.github.com/jakenuts/eeb56da402b571ba6ca30c4fcffc7247 (2认同)