【发布时间】:2017-06-14 21:30:08
【问题描述】:
在 ASP.NET Core / EntityFramework Core 中,services.AddDbContext 方法会将指定的上下文添加为范围服务。据我了解,这是 Microsoft 建议的 dbcontext 生命周期管理。
但是,我们的工程师部门对此有很多争论,许多人认为需要尽快处理上下文。那么,将 dbcontext 配置为 Transient 并保持通常使用的相同存储库模式(即将上下文直接注入存储库的构造函数)以及支持灵活的单元测试的最佳方法是什么?
【问题讨论】:
-
嗯,Transient DbContext 的一个缺点是,你失去了工作单元功能,除非你自己实现它。默认情况下,DbContext 是瞬态的,因此在请求期间有效,所有服务(不仅是控制器)都将收到它的相同实例。如果出现问题,您可以将其回滚/不发出 SaveChanges 命令。使用瞬态你会失去它,每个服务都会有自己的 DbContext 实例。
-
另外我认为它没有多大价值,因为您通过构造函数注入 DbContext 并且您必须确保在您的服务中不会在处理后调用它。如果你真的需要 DbContext 的生命周期很短,最好创建一个像包装器这样的工厂来返回瞬态工厂并将默认的 DbContext 留给作用域
-
我观察到的技术是开发人员将 dboptions 注入控制器并将其传递给各种服务。然后,相应的服务从服务内(使用提供的选项)实例化一个新的上下文,并将其传递给服务内的各种方法。从我的角度来看,这与使 dbcontext 瞬态没有什么不同,但也许我错过了这种实现的有益细微差别。
-
手动注入 dboptions 并将其传递给调用服务与首先拥有 DI/IoC 系统的目的相比。您可以在瞬态工厂中抽象所有这些并注入工厂,然后在您的代码中调用它,例如
using(var context = transientDbContextFactory.Create()) { ... },以解决您需要瞬态上下文并将其保留在应用程序其余部分的范围内的情况。 -
@Tseng 您的第一条评论不太正确,您说“默认情况下 DbContext 是瞬态的”,而实际上它是默认范围的。然后,您继续将其描述为“因此在请求期间有效”,这是对 scoped 作用的描述!所以我认为第一部分只是一个意外。只是在我阅读您的评论时将其放在那里,这让我在几分钟内完全怀疑我对范围与瞬态的了解????
标签: c# asp.net-core entity-framework-core