我的工作单元和存储库的实现可能是此处问题的根源..但考虑到我在哪里寻找工作单元< / em>实现我看到了另一个,我确信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);
我发现的问题是,每个存储库似乎都有自己的实例,加上工作单元也有自己的实例 - 因此当我尝试提交事务时我得到的异常(关于交叉的东西) -context transaction)。
最重要的是,在某些特定情况下,我需要连接字符串是动态的,这样工作单元可以处理用户选择的数据库 - 因此工厂的“需要”。
结果是每个存储库有<1个连接,每个工作单元有<1个连接 ,这违背了UoW的目的(即事务数据操作),并且所有我认为,这种开销会导致严重的性能问题(在3-4小时内运行+/- 200,000次小数据操作!!)。
这就是我创建工作单元实例的方式;我希望能够在那里注入存储库实现,但仍然能够使用用户要求的连接字符串:
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
发挥作用的地方吗?
答案 0 :(得分:0)
Argh ..再次做到了(在过早的绝望中发布后不久找到答案)。我想要的是工作单元工厂实际上创建存储库。所以答案很简单:我没有注入IRepository<T>
,而是创建了一个接口IRepositoryFactory<T>
并注入了它:
public interface IRepositoryFactory<T> where T : class
{
IRepository<T> Create(DataContext context);
}
这样,使用用户选择的连接字符串的 MyUoWFactory 的Create
方法只能创建一个上下文并将其传递给所有存储库工厂:
public MyUoWFactory(IRepositoryFactory<Type1> type1repoFactory, IRepositoryFactory<Type2> type2repoFactory,
IRepositoryFactory<Type3> type3repoFactory, IRepositoryFactory<Type4> type4repoFactory,
IRepositoryFactory<Type5> type5repoFactory, IRepositoryFactory<Type6> type6repoFactory)
{
_type1RepositoryFactory = type1repoFactory;
_type2RepositoryFactory = type2repoFactory;
_type3RepositoryFactory = type3repoFactory;
_type4RepositoryFactory = type4repoFactory;
_type5RepositoryFactory = type5repoFactory;
_type6RepositoryFactory = type6repoFactory;
}
public IUnitOfWork Create(string userSelectedConnectionString)
{
var context = new MyDataContext(userSelectedConnectionString)
return new MyUoW(context,
_type1RepositoryFactory.Create(context),
_type2RepositoryFactory.Create(context),
_type3RepositoryFactory.Create(context),
_type4RepositoryFactory.Create(context),
_type5RepositoryFactory.Create(context),
_type6RepositoryFactory.Create(context));
}