c# - EF6 DbContext IOC 依赖

标签 c# entity-framework visual-studio-2013 dependency-injection windows-services

我在 Windows 服务/控制台应用程序中使用 EF6。我已经成功 为我的业务层接口(interface)和实现实现了 IOC/DI。 使用构造函数注入(inject)。我也在使用对象数据库、任务并行库。以获得更好的性能,我对此感到满意。

同时使用 System.IO.Abstractions使我的代码更易于测试。

EF6 使用 .tt 文件为所有域实体创建 POCO 类 便利。为了执行数据库查询,我在每个地方都写了

using(var db = new MyContext())
{
// code reading from/writing to database
...
...
}

我知道这不是正确的做法,并且会在我的代码的各个地方发出噪音。 我想让它松耦合。现在进行我的数据库操作 - 我是 对如何前进以使其更具可测试性和松散耦合感到困惑。任何人都可以给我一个很好的例子,可以引用的文章。

我想要实现的 2 件主要事情是对 连接字符串配置(用于各种服务器部署)并使 DbContext 在我的代码中非常松散地耦合。

最佳答案

为了解决耦合(和测试)问题,您可以为您的 DbContext (IMyDbContext) 创建自己的接口(interface),并重新公开所有类型化实体 DbSets SaveChanges(),可能还有一些其他方法。您还应该将此接口(interface)设置为 Disposable

public interface IMyDbContext : IDisposable
{
    IDbSet<Foo> Foos { get; set; }
    IDbSet<Bar> Bars { get; set; }

    int SaveChanges();
    DbEntityEntry<T> Entry<T>(T entity) where T : class;
}

(您还可以考虑接口(interface)的只读和读写版本)

然后更改您的具体 DbContext 以实现此接口(interface)。您现在与 DbContext 合理分离(用于单元测试等),但仍然可以访问 IQueryable 的有用性、工作的固有单元以及由DbContext

然后,这里有两个选项可以将 IMyDbContext 注入(inject)到您的业务/服务类中

  1. IDbContext 的构造函数注入(inject)

  1. 为创建具体的 DbContext 创建一个 Factory 方法和一个 Factory 接口(interface),然后对 IMyDbContextFactory 工厂接口(interface)进行构造函数注入(inject)(您需要接口(interface),而不是混凝土工厂,同样用于模拟测试目的)。

此处的选择取决于您需要对 DbContext 执行的操作。 #1 在 IoC 容器中配置可能很棘手,因为您需要将生命周期管理移交给容器。但是,如果可以为每个请求配置新实例,那么这在 Web 应用程序中可能是有益的,这样如果请求(假定为单线程)可以将其用作缓存。

我个人更喜欢#2,因为它允许直接管理上下文:

using(var db = _myContextFactory.CreateDB())
{
    db.SaveChanges();
}

但很明显,我们随后失去了缓存等长期存在的上下文的任何潜在好处。但如果需要,还有许多其他缓存替代技术。

一个警告:DbContext 根本不是线程安全的 - 如果您使用 TPL,请确保每个任务都获得自己的 DbContext 实例 - 例如使用 Parallel.For/ForEachlocalinit 重载来实例化它。

关于c# - EF6 DbContext IOC 依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27864702/

相关文章:

unit-testing - 如何对存储库方法进行单元测试

c# - 什么时候在 DbContext 上执行查询

entity-framework - 如何在EF中使用Lambda包含?

c# - SQL Server CLR 与第 3 方 SDK 集成 : Error on missing assembly System. 绘图

javascript - Components.classes 错误 - VS 2013 中的 FireFox 附加组件(扩展)

c# - Xamarin.Forms 中的错误 "Frame not in module."- Android 项目

c# - 从 OnTriggerXXX 函数获取 ContactPoint2D/接触法线

visual-studio-2012 - 安装 Visual Studio 2013 Preview 会搞砸 2012 年吗?

c# - 带有两个标签的 Specflow 场景打开两个窗口

c# - 使用 netTcpBinding 时,在 WCF 中实现加密的最简单方法是什么?