注入DataContext ...并且只能有一个

时间:2013-05-03 14:12:16

标签: c# ninject

我的工作单元存储库的实现可能是此处问题的根源..但考虑到我在哪里寻找工作单元< / 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发挥作用的地方吗?

1 个答案:

答案 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));
}