我对工作单元和存储库的实现可能是这里问题的根源。但鉴于我到处寻找工作单元实现,我看到的是不同的,我确信 Ninject 有解决它的方法。
所以我将实现注入IRepository<T>
到我的“工作单元”的构造函数中。
_kernel.Bind<IRepository<SomeType1>>().To<RepoOfSomeType1>().WhenInjectedInto<IMyUoWFactory>();
_kernel.Bind<IRepository<SomeType2>>().To<RepoOfSomeType2>().WhenInjectedInto<IMyUoWFactory>();
...
我已经设置内核来实例化一个DataContext
单例范围,我认为这意味着我在需要时注入这个 DataContext的同一个实例:
_kernel.Bind<DataContext>().ToConstructor(arg => new MyDataContext(arg.Inject<string>()))
.InSingletonScope() // pass same instance to all repositories?
("connection", _someConnectionString);
我发现的问题是,每个存储库似乎都有自己的实例,而且工作单元也有自己的实例 - 因此当我尝试提交事务时遇到异常(关于跨上下文事务)。
最重要的是,在某些特定情况下,我需要连接字符串是动态的,以便工作单元可以处理用户选择的数据库 - 因此“需要”工厂。
结果是每个存储库有 1 个连接加上每个工作单元有 1 个连接,这违背了 UoW 的目的(即事务数据操作),我认为所有这些开销都会导致严重的性能问题(运行 +/- 200,000小数据操作... 3-4 小时!!)。
这就是我创建工作单元实例的方式;我希望能够在那里注入存储库实现,但仍然能够使用用户要求的连接字符串:
public MyUoWFactory(IRepository<Type1> type1repo, IRepository<Type2> type2repo,
IRepository<Type3> type3repo, IRepository<Type4> type4repo,
IRepository<Type5> type5repo, IRepository<Type6> type6repo)
{
_type1Repository = type1repo;
_type2Repository = type2repo;
_type3Repository = type3repo;
_type4Repository = type4repo;
_type5Repository = type5repo;
_type6Repository = type6repo;
}
public IUnitOfWork Create(string userSelectedConnectionString)
{
return new MyUoW(new MyDataContext(userSelectedConnectionString),
_type1Repository, _type2Repository, _type3Repository,
_type4Repository, _type5Repository, _type6Repository);
}
使用我定义的内核绑定,这会导致存储库的 DataContext 指向内核指示的位置,而创建的 UoW 的 DataContext 指向用户请求的位置。
我怎样才能在不求助于服务定位器的情况下完成这项工作?我需要存储库在应用程序启动时而不是在用户选择数据库之后注入它们的 DataContext。这是Ninject.Factory
发挥作用的地方吗?