我在这里使用 EF6 的通用统一工作: https://genericunitofworkandrepositories.codeplex.com/
我有一个使用两个数据库的应用程序。我创建了额外的 UnitOfWork 接口(interface)和实现原始工作单元接口(interface)的类:
namespace Repository.Pattern.UnitOfWork
{
public interface ILotteryBackOfficeUnitOfWorkAsync : IUnitOfWorkAsync
{
}
}
第二个数据库初始化的第二个工作单元类型:
namespace Repository.Pattern.Ef6
{
public class LotteryBackOfficeUnitOfWork : UnitOfWork, ILotteryBackOfficeUnitOfWorkAsync
{
public LotteryBackOfficeUnitOfWork(IDataContextAsync dataContext)
: base(dataContext)
{ }
}
}
在统一中,我为不同的数据上下文注册了两个工作单元:
public static void RegisterTypes(IUnityContainer container)
{
// NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
// container.LoadConfiguration();
// TODO: Register your types here
// container.RegisterType<IProductRepository, ProductRepository>();
var purusLotteryConnectionString = WebConfigurationManager.ConnectionStrings["PurusLotteryContext"].ConnectionString;
var purusLotteryBackOfficeConnectionString = WebConfigurationManager.ConnectionStrings["PurusLotteryBackOfficeContext"].ConnectionString;
container.RegisterType<IDataContextAsync, PurusLotteryContext>(new InjectionConstructor(purusLotteryConnectionString));
container.RegisterType<IUnitOfWorkAsync, UnitOfWork>(new HierarchicalLifetimeManager());
container.RegisterType<IDataContextAsync, PurusLotteryBackOfficeContext>("LotteryBackOfficeContext", new InjectionConstructor(purusLotteryBackOfficeConnectionString));
container.RegisterType<ILotteryBackOfficeUnitOfWorkAsync, LotteryBackOfficeUnitOfWork>(new HierarchicalLifetimeManager(),
new InjectionConstructor(container.Resolve<IDataContextAsync>("LotteryBackOfficeContext")));
container.RegisterType<IHomeService, HomeService>();
}
它有效,但这是正确的程序吗?
最佳答案
我看到的一个错误是您在注册阶段解决了。这不仅是危险的(因为是 explained 在不同的 DI 库的文档中),在你的情况下它会导致 PurusLotteryBackOfficeContext
用作常量,因此作为 Singleton 注入(inject)到 LotteryBackOfficeUnitOfWork
中.换句话说,虽然这在开发过程中似乎可行,但实际上行不通,因为 DbContext
can't be used as singleton .
相反,您应该尽可能多地使用 Unity 的 Autowiring 功能,否则 DI 库与构建对象图相比没有优势(只有劣势)by hand .
除此之外,您还违反了 Liskov Substitution Principle (LSP) 在您的设计中,这会给您的 DI 配置带来麻烦。您违反了 LSP,因为您对同一抽象有两个不兼容的实现。两者 PurusLotteryContext
和 PurusLotteryBackOfficeContext
实现 IDataContextAsync
,但它们是不兼容的,因为它们不能互换,因为它们都在完全不同的数据库模式上工作。尽管它们可能看起来共享相同的接口(interface),但它们并不共享相同的契约。看看当你注入(inject) PurusLotteryContext
时会发生什么进入一些需要与后台一起工作的类(class)。应用程序将中断,这意味着您违反了 LSP。
解决方案是为它们提供独立的抽象。乍一看,这似乎是一件很奇怪的事情,因为它们都有相同的方法。但是请记住,接口(interface)不仅仅是一组方法签名;一个接口(interface)描述了一个契约和行为,并且由于两个实现都在一个完全不同的数据库模式上工作,所以它们有一个完全不同的契约。当您将其分开时,您的代码将如下所示:
public class PurusLotteryContext : IPurusLotteryDataContextAsync {
public PurusLotteryContext(string conString) : base(conString) { }
}
public class LotteryUnitOfWork : ILotteryUnitOfWorkAsync {
public LotteryUnitOfWork(IPurusLotteryDataContextAsync dc) { }
}
public class PurusLotteryBackOfficeContext : IPurusLotteryBackOfficeDataContextAsync {
public PurusLotteryBackOfficeContext(string conString) : base(conString) { }
}
public class LotteryBackOfficeUnitOfWork : ILotteryBackOfficeUnitOfWorkAsync {
public LotteryBackOfficeUnitOfWork(IPurusLotteryBackOfficeDataContextAsync dc) { }
}
这允许您进行以下注册:
container.Register<IPurusLotteryDataContextAsync>(new HierarchicalLifetimeManager(),
new InjectionFactory(c => new PurusLotteryContext(purusLotteryConnectionString)));
container.Register<IPurusLotteryBackOfficeDataContextAsync>(
new HierarchicalLifetimeManager(),
new InjectionFactory(c => new PurusLotteryBackOfficeContext(
purusLotteryBackOfficeConnectionString)));
container.RegisterType<ILotteryUnitOfWorkAsync, LotteryUnitOfWork>(
new HierarchicalLifetimeManager());
container.RegisterType<ILotteryBackOfficeUnitOfWorkAsync, LotteryBackOfficeUnitOfWork>(
new HierarchicalLifetimeManager());
注意关于这个注册的一些事情:
- 数据上下文实现被注册为分层的,因为您通常需要 Entity Framework DbContext to have a 'per request' lifestyle .
- 与使用容器的 Autowiring 功能相比,数据上下文实现是使用工厂注册的。这是因为 Autowiring 对这些类没有帮助,工厂委托(delegate)不仅会使注册更简单,而且类型更安全(如果我们出错,编译器会帮助我们)。
关于c# - Unity Container - 具有通用工作统一性的多个数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33981713/