【问题标题】:Injecting a DataContext... and there can be only one注入一个DataContext...并且只能有一个
【发布时间】:2013-05-03 23:00:36
【问题描述】:

我的工作单元存储库的实现可能是这里问题的根源。但考虑到我到处寻找工作单元 实现我看到了一个不同的实现,我确信 Ninject 有办法解决它。

所以我将IRepository<T> 的实现注入到我的“工作单元”的构造函数中。

_kernel.Bind<IRepository<SomeType1>>().To<RepoOfSomeType1>().WhenInjectedInto<IMyUoWFactory>();
_kernel.Bind<IRepository<SomeType2>>().To<RepoOfSomeType2>().WhenInjectedInto<IMyUoWFactory>();
...

我已将内核设置为在 singleton 范围 中实例化 DataContext,我认为这意味着每当我注入此 DataContext 的相同实例需要它:

_kernel.Bind<DataContext>().ToConstructor(arg => new MyDataContext(arg.Inject<string>()))
                           .InSingletonScope() // pass same instance to all repositories?
                           ("connection", _someConnectionString);

我发现的问题是,每个存储库似乎都有自己的实例,而且工作单元也有自己的实例 - 因此当我尝试提交事务时遇到异常(关于交叉-上下文事务)。

最重要的是,在某些特定情况下,我需要连接字符串是动态的,以便工作单元可以处理用户选择的数据库 - 因此“需要”工厂。

结果是我有 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 发挥作用的地方吗?

【问题讨论】:

    标签: c# ninject


    【解决方案1】:

    Argh.. 又做了一次(在过早的绝望中发布后不久就找到了答案)。我想要的是工作单元工厂来实际创建存储库。所以答案很简单:我没有注入IRepository&lt;T&gt;,而是创建了一个接口IRepositoryFactory&lt;T&gt; 并注入了它:

    public interface IRepositoryFactory<T> where T : class
    {
        IRepository<T> Create(DataContext context);
    }
    

    这样,MyUoWFactoryCreate 方法采用用户选择的连接字符串只能创建一个上下文并将其传递给所有存储库工厂:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-26
      • 2016-02-20
      • 2021-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-07
      相关资源
      最近更新 更多