避免用using包装DbContext【翻译】

本文探讨了在ASP.NET MVC5应用中,使用Entity Framework 6 (EF6)时,多个DbContext实例导致的问题。当多个上下文尝试操作相同实体时,可能会出现数据同步困难。解决方案是通过引入Autofac依赖注入容器,实现DbContext和相关服务的单例生命周期管理,确保每个请求只创建一次DbContext实例。文章详细介绍了如何配置Autofac,以及如何修改控制器和服务以利用依赖注入,从而遵循显式依赖原则,提高代码的可维护性和解耦性。

与using语句和DbContext密切相关的问题是:如果有多个DbContext(因为该using语句通常会创建一个新实例)。
“如果您有多个DbContext尝试使用相同的实体实例,那么您将承受巨大的痛苦。”
考虑这个简单的示例,它包含了一个Controller和一个service,两者同时在使用dbContext。

假设在Index方法中,从数据库中读取 starship时,它的name属性值为“ Millenium Falcon”。下次访问Index时,name属性值是什么?

SaveChanges()被调用时不执行任何操作。db实例在StarshipService中并未跟踪该实体。所以名称将保持不变。
那么,我们可以这样解决这个问题。让我们附加实体。这是更新后的service:

再次运行。现在Name的值是什么?

SaveChanges()仍然不执行任何操作。实体的name被更新,该实体依然未跟踪。
让我们再尝试一次:

现在,它会起作用吗?你觉得如何?

是的,现在name的值已更新为“ Millenium Falcon *”,下次是“ Millenium Falcon **”,等等。

要正确地得到预期的行为,需要进行大量的尝试工作。这段代码是脆弱且重复的,更糟的是,具有隐藏的暂存依赖性。

那么,MVC5/EF6的旧代码中要怎么使用Autofac呢?

安装Nuget软件包
安装Autofac.MVC5 nuget软件包。与.NET Framework nuget包不同,它不会添加一堆类,但你仍然需要将它们连接起来。
进到global.asax文件中更新Application_Start():

当你成功运行它,你还可以把它们放置到一个模块中,并把它的helper放到在App_Start目录中。

这部分代码中所做的事情有:

配置Autofac的依赖项容器
设置它,以创建controller
设置它,以创建 ApplicationDbContext
设置它,以创建 StarshipService
使用 InstancePerRequest设置上面两个
配置MVC5以使用Autofac来解决其依赖性
这可能也就需要用5分钟。更新之后还会有混乱的代码吗?好了,服务现在看起来像这样:

另外,控制器现在看起来像这样:

请注意,这两种类型现在都遵循显式依赖项原则。同时注意到,在解耦之后的代码没完全没有new关键字,这与显式依赖原则有关。

            “方法和类应显式要求(通常通过方法参数或构造函数参数)它们所需要的协作对象才能正常运行。”

不用对所引用对象的隐式依赖感到惊讶。如果需要引用某个类,应该在构造函数中引入它(注:依赖注入)。如果要将类进行解耦,,则应该声明一个抽象类(或接口),而不是直接使用new创建实例或者调用静态方法。
Absorbing material: www.goodsmaterial.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值