Ninject 和 DbContext

Ninject and DbContext

使用 EF 6 和 Ninject 3.2.2 构建应用程序 我在思考如何以智能方式访问 DbContext 时遇到了一些麻烦。

据我所知,在 Ninject 的较新版本中,仅鼓励构造函数注入。作为 EF 6,它本身是存储库和工作单元,我没有在 EF 之上做任何抽象。 如果希望能够使用多个小的工作单元,那么将 DbContext (uow) 注入每个需要它的 class 是行不通的。 在非国际奥委会的方式我会这样做:

Using(var db = new DbContext){}

如何使用 Ninject 实现此目的,因为我不再可以在我的 using 块中使用 kernel.get...

我会考虑两种方法:

  1. 创建通用的 DbContext,可以隐藏在接口后面:

    public interface IPortalContext : IDisposable
    {
        DbSet<User> Users { get; }
    
        DbContext Context { get; }
    }
    
    public class PortalContext : DbContext, IPortalContext
    {
        public PortalContext()
            : base("PortalConnectionString")
        {
        }
    
        public virtual DbSet<User> Users { get; set; }
    }
    

    然后您可以毫无问题地将上下文注入构造函数。

  2. 创建许多可用于不同场景的小上下文类。

我不认为第一种方法不好,因为它只封装了您的 DbSetsDbContext,使其更易于注入和测试。您没有在 EF 之上创建任何不必要的层,整个界面看起来非常透明。

无论如何,这种方法比让整个 IRepository<T> 东西访问另一个存储库要好...

我不知道你所说的 "multiple small unit of works" 是什么意思,但只是为了曝光,这是我在最近的应用程序中所做的:

  1. 在小的有界上下文中划分域(这更像是一个概念步骤)
  2. 每个限界上下文都有:上下文、存储库、存储库工厂
  3. 每个上下文实现一个 IContext 和一个提供基本方法和公共属性的 BaseContext(IContext 将对模拟有用)
  4. 每个存储库都将相关上下文作为构造函数参数
  5. 这是存储库工厂的示例

    public class CartRepositoryFactory : IRepositoryFactory { public IRepository 生成(CartContext ctx) { return 新的 CartRepository(ctx); } }

  6. 在应用服务层,我注入了一个UoW和我需要的repository factory

  7. 如果我想在一个服务中使用多个不同的上下文,我只需创建另一个服务并组合我需要的服务,然后注入它们

您可能会问,但是为什么?!?这太疯狂了!!

嗯,因为如果 Repository 管理 DbContext,那么每个 class 实例化我只能执行一个操作。这允许我打开 DbContext 并多次调用存储库。 当然现在你在应用程序服务级别也有同样的问题,你只能在每个实例化中调用一个方法,但它更容易管理。

最终这一切都取决于您的喜好:您是想要精简服务还是精简存储库?