0

I recently determined在.NET Core中使用Dependency Injected DbContext并使用异步等待调用没有显着的性能收益,而不是每次我想访问数据库时创建新的DbContext。为什么创建一个新的DbContext比Dependency Injected慢?

但现在我需要知道为什么。

我在.NET Core 1.1 API服务(控制器正在调用)中使用System.Diagnostics.Stopwatch进行了更细化的测试,其中只有在访问数据库时才运行秒表。结果令人惊讶。

当使用标准的依赖注入上下文和异步/等待来电:

var task1 = _InjectedDbContext.Table1.FirstOrDefaultAsync(p => p.Id == SomeId); 
var task2 = _InjectedDbContext.Table2.Where(u => u.AnotherId == SomeOtherId).ToListAsync(); 

(var result1, var result2) = await (task1, task2).WhenAll(); 

各的DbContext查询显著花了不到100毫秒。

但是,使用这种方法时:

using (var context = new DbContext(_InjectedContextOptions.Options)) 
{ 
    var task1 = context.Table1.FirstOrDefaultAsync(p => p.Id == SomeId); 
    var task2 = context.Table2.Where(u => u.AnotherId == SomeOtherId).ToListAsync(); 

    (var result1, var result2) = await (task1, task2).WhenAll(); 
} 

每个的DbContext查询少则100-230毫秒了。

仅供参考,这里是我的DI设置在Startup.cs ConfigureServices代码:

var connection = Configuration.GetConnectionString("mydb"); 
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(connection)); 

这里是我提供DbContextOptions因为每当我创建一个新的DbContext一个单码:

var dbContextOptions = new DbContextOptionsBuilder<MyDbContext>();   
dbContextOptions.UseSqlServer(Configuration.GetConnectionString("MyDb")); 
services.AddSingleton(dbContextOptions); 

我还确定,滞后不是由使用语句(这是一个非常快速的操作)中创建的DbContext而引起的。这里发生了什么?是否每次都试图重新连接到数据库?

+0

你是怎么注册你的DbContext的?因为在应用程序的持续时间内,DI可能会在内存中保存DbContext的副本。该请求或一个调用基于您注册DbContext的范围。这将解释性能增益。 –

+0

嗨,好问题。在两种情况下,我都用DI的代码更新了我的问题。生命期是在默认情况下:https://stackoverflow.com/questions/37507691/entity-framework-core-service-default-lifetime – starmandeluxe

+0

@RickvandenBosch:AddDbContext的默认注册是有作用域的,所以它的解决每个请求,所以,应该没关系。您是否偶然在单个请求期间创建大量的DbContext实例?通常DbContext会回收连接,但是如果你创建大量的连接,可能是它的原因 – Tseng

回答

0

您正在使用AddDbContext方法,用于您在第一个场景中使用的DbContext,它将DbContext作为Scoped添加到服务中(如果我没有错误的话)。 DbContext可能是因为优化而添加服务时初始化的(这里不确定)。对于第二种情况,您正在创建一个新的DbContext。除了创建DbContext之外,还有一些其他的东西需要完成。

this post两者,这里有一些提示,以“热身”您的上下文:

  1. 使用缓存DB示范店
  2. 生成预编译的意见
  3. 生成的预编译的版本使用n-gen避免碰撞的实体框架

上面的提示表明,使用DbContext比使用DbContext更多,而不仅仅是新建一个并开始查询。

+0

我同意你关于DI初始化的第一点。但我只是不确定这些优化:这不会帮助我在这里介绍的两种方法的性能,而不仅仅是新的上下文方法吗?我更感兴趣的是解释两者之间的差异,而不是提高EF性能的一般技巧。另外,我只做了DbContext的基准测试,这是一个非常微不足道的性能... – starmandeluxe

+0

嗨@starmandeluxe,正如我前面所说:我可以想象在AddDbContext方法中有一些优化,导致DI场景更快。这些提示仅用于显示有提高性能的空间,这些可能已经在AddDbContext方法中实现,导致它比自己新建一个更快。 –

+0

@RickvandenBosch我会认为问题在于事物是如何计时的。 – Mardoxx

相关问题