我应该如何管理MVCCore中的DbContext生命周期?从文档EntityFrameworkcontextshouldbeaddedtoservicecontainerwithScopedlifetime.如果您使用如上所示的辅助方法,则会自动完成此操作。将使用实体框架的存储库应该使用相同的生命周期。我一直认为我应该为我必须处理的每个工作单元创建一个新的Context。这让我想到,如果我有一个ServiceA和ServiceB在DbContext上应用不同的操作,它们应该得到一个不同的DbContext实例。文档内容如下:回到ServiceA和ServiceB,对我来说,Transient更合适。我研究过每个HttpRequest只能保存一次上下文,但我真的不明白这是如何工作的。特别是如果我们看一个服务:using(vartransaction=dbContext.Database.BeginTransaction()){//创建一些实体varsomeEntity=newSomeEntity();dbContext.SomeEntity.Add(someEntity);//保存以获取实体的iddbContext.SaveChanges();//创建关联实体varrelatedEntity=newRelatedEntity{SomeEntityId=someEntity.Id};dbContext.RelatedEntity.Add(relatedEntity)dbContext.SaveChanges();事务.提交();在这里我们需要保存上下文以获取与我们刚刚创建的另一个实体相关的实体的ID。同时,另一个服务可以更新相同的上下文。据我所知,DbContext不是线程安全的。在这种情况下我应该使用Transient吗?为什么文档建议我应该使用Scoped?我错过了框架的一些重要部分吗?正如其他人已经解释的那样,您应该使用对数据库上下文的作用域依赖,以确保它可以被正确重用。对于并发,请记住您也可以异步查询数据库,因此您可能不需要实际的线程。如果您确实需要线程,即后台工作者,那么它们的生命周期可能与请求不同。因此,这些线程不应使用从请求范围检索到的依赖项。当请求结束并且它的依赖范围关闭时,一次性依赖被适当地处理。对于其他线程,这意味着它们的依赖项可能最终会被释放,尽管它??们仍然需要它们:坏主意。相反,您应该为您创建的每个线程显式打开一个新的依赖范围。您可以通过注入IServiceScopeFactory并使用CreateScope创建作用域来完成此操作。结果对象将包含一个服务提供者,您可以从中检索依赖项。由于这是一个单独的范围,因此范围依赖项(例如范围数据库上下文)将在此范围的生命周期内重新创建。为避免陷入服务定位器模式,您应该考虑让线程执行集中式服务,将所有必需的依赖项集中在一起。然后线程可以这样做:using(varscope=_scopeFactory.CreateScope()){服务.Run();然后BackgroundThreadService及其所有依赖项可以遵循接收依赖项的通用依赖项注入方法。我相信在大多数情况下使用作用域生命周期不会出现并发问题。即使在发布的示例中,也没有并发问题,因为随后将调用当前请求中的服务。我什至无法想象在一个HTTP请求(范围)的上下文中并行运行2个或更多服务(可能但不常见)。Lifecycle只是一种存储数据的方式(这里简单)。只要看看流行的DI框架中的一些tenuredmanagers,它们都工作得很好——它只是实现了一次性模式的对象之类的字典。对于Transient,我相信您的get对象方法将始终返回null,因此DI将在每次请求时创建新实例。SingleInstance会将对象存储在类似于静态并发字典的东西中,因此容器只会创建一次实例,然后接收现有实例。Scoped通常指的是用来存放创建对象的作用域对象。在aspweb管道中,它通常意味着与每个请求相同(因为范围可以通过管道传输)简短-不要担心只使用范围它是安全的,您可以根据要求调用它。我的解释尽量简单,你可以随时查看源代码并找到你需要的匹配细节https://github.com/aspnet/DependencyInjection以上是C#学习教程:HowshouldImanageDbContextinMVC核心寿命?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
