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...
我会考虑两种方法:
创建通用的 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; }
}
然后您可以毫无问题地将上下文注入构造函数。
创建许多可用于不同场景的小上下文类。
我不认为第一种方法不好,因为它只封装了您的 DbSets
和 DbContext
,使其更易于注入和测试。您没有在 EF 之上创建任何不必要的层,整个界面看起来非常透明。
无论如何,这种方法比让整个 IRepository<T>
东西访问另一个存储库要好...
我不知道你所说的 "multiple small unit of works" 是什么意思,但只是为了曝光,这是我在最近的应用程序中所做的:
- 在小的有界上下文中划分域(这更像是一个概念步骤)
- 每个限界上下文都有:上下文、存储库、存储库工厂
- 每个上下文实现一个 IContext 和一个提供基本方法和公共属性的 BaseContext(IContext 将对模拟有用)
- 每个存储库都将相关上下文作为构造函数参数
这是存储库工厂的示例
public class CartRepositoryFactory : IRepositoryFactory
{
public IRepository 生成(CartContext ctx)
{
return 新的 CartRepository(ctx);
}
}
在应用服务层,我注入了一个UoW和我需要的repository factory
- 如果我想在一个服务中使用多个不同的上下文,我只需创建另一个服务并组合我需要的服务,然后注入它们
您可能会问,但是为什么?!?这太疯狂了!!
嗯,因为如果 Repository 管理 DbContext,那么每个 class 实例化我只能执行一个操作。这允许我打开 DbContext 并多次调用存储库。
当然现在你在应用程序服务级别也有同样的问题,你只能在每个实例化中调用一个方法,但它更容易管理。
最终这一切都取决于您的喜好:您是想要精简服务还是精简存储库?
使用 EF 6 和 Ninject 3.2.2 构建应用程序 我在思考如何以智能方式访问 DbContext 时遇到了一些麻烦。
据我所知,在 Ninject 的较新版本中,仅鼓励构造函数注入。作为 EF 6,它本身是存储库和工作单元,我没有在 EF 之上做任何抽象。 如果希望能够使用多个小的工作单元,那么将 DbContext (uow) 注入每个需要它的 class 是行不通的。 在非国际奥委会的方式我会这样做:
Using(var db = new DbContext){}
如何使用 Ninject 实现此目的,因为我不再可以在我的 using 块中使用 kernel.get...
我会考虑两种方法:
创建通用的 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; } }
然后您可以毫无问题地将上下文注入构造函数。
创建许多可用于不同场景的小上下文类。
我不认为第一种方法不好,因为它只封装了您的 DbSets
和 DbContext
,使其更易于注入和测试。您没有在 EF 之上创建任何不必要的层,整个界面看起来非常透明。
无论如何,这种方法比让整个 IRepository<T>
东西访问另一个存储库要好...
我不知道你所说的 "multiple small unit of works" 是什么意思,但只是为了曝光,这是我在最近的应用程序中所做的:
- 在小的有界上下文中划分域(这更像是一个概念步骤)
- 每个限界上下文都有:上下文、存储库、存储库工厂
- 每个上下文实现一个 IContext 和一个提供基本方法和公共属性的 BaseContext(IContext 将对模拟有用)
- 每个存储库都将相关上下文作为构造函数参数
这是存储库工厂的示例
public class CartRepositoryFactory : IRepositoryFactory { public IRepository 生成(CartContext ctx) { return 新的 CartRepository(ctx); } }
在应用服务层,我注入了一个UoW和我需要的repository factory
- 如果我想在一个服务中使用多个不同的上下文,我只需创建另一个服务并组合我需要的服务,然后注入它们
您可能会问,但是为什么?!?这太疯狂了!!
嗯,因为如果 Repository 管理 DbContext,那么每个 class 实例化我只能执行一个操作。这允许我打开 DbContext 并多次调用存储库。 当然现在你在应用程序服务级别也有同样的问题,你只能在每个实例化中调用一个方法,但它更容易管理。
最终这一切都取决于您的喜好:您是想要精简服务还是精简存储库?