【问题标题】:Setting the connection string of a DBContext in my repository class using Ninject使用 Ninject 在我的存储库类中设置 DBContext 的连接字符串
【发布时间】:2015-02-24 12:24:03
【问题描述】:

我有一个 MVC 5 应用程序,它使用 EF 6 并使用 DI 容器 Ninject 通过依赖注入实现存储库模式。 dbcontext 的连接字符串存储在 EF 上下文正确找到的 Web.config 文件中。一切正常。最近,我需要在运行时确定与我的 DBContext 的连接并连接到不同的数据库(但具有完全相同的结构)。因此,在实例化存储库之前,我需要在运行时从实体连接字符串中更改 sql 连接字符串部分。我真的很感激一些帮助。我不是 DI 大师;知道足够的 Ninject 来让我的事情顺利进行。

这是我的存储库基础接口:

public interface IRepositoryBase<T> where T : class
{
    void Add(T entity, string userGuid = "");
    void Delete(T entity);
    // ... removed other method signatures for brevity
}

我的存储库基础实现:

public abstract class RepositoryBase<D, T> : IRepositoryBase<T>, IDisposable
where T : class
where D : DbContext, new()
{
    private Guid? currUserGuid = null;
    private D dataContext;
    protected D DataContext
    {
        get
        {
            if (dataContext == null)
                dataContext = new D();
            return dataContext;
        }
        set { dataContext = value; }
    }

    public IQueryable<T> FindBy(Expression<Func<T, bool>> predicate)
    {
        return DataContext.Set<T>().Where(predicate);
    }
    public virtual IQueryable<T> GetAll()
    {
        IQueryable<T> query = DataContext.Set<T>();
        return query;
    }

    public virtual void Delete(T entity)
    {
        OperationStatus stat = TryDelete(entity);
    }
    // .... removed rest for brevity
}

具体类的接口和实现:

    public interface ICustomerRepository : IRepositoryBase<Customer>
{
    Customer GetCustomerAndStatus( Guid custGuid );
}
public class CustomerRepository : RepositoryBase<PCDataEFContext, Customer>, ICustomerRepository
{
    public Customer GetCustomerAndStatus( Guid custGuid )
    {
        return DataContext.Customers.Include( x => x.CustStatusType )
        .SingleOrDefault( x => x.PKGuid == custGuid );
    }
}

我的 Ninject 依赖解析器:

    public class NinjectDependencyResolver : IDependencyResolver
{
    private IKernel kernel;

    public NinjectDependencyResolver()
    {
        kernel = new StandardKernel();
        AddBindings();
    }
    public IKernel Kernel { get { return kernel; } }

    private void AddBindings()
    {
        kernel.Bind<ICustomerRepository>().To<CustomerRepository>();
        // ... other bindings are omitted for brevity
    }
}

最后,这是我的实体框架生成的 DBContext:

public partial class PCDataEFContext : DbContext
{
    public PCDataEFContext()
        : base("name=PCDataEFContext")
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }

    public virtual DbSet<Customer> Customers { get; set; }
}

以上所有代码都很好用!但正如我在开始时所说,我不知道如何在运行时将连接字符串注入到我的 Repositorybase 类中,这样我就不必修改任何继承的存储库(我有很多)。有人请帮忙。

巴布。

【问题讨论】:

    标签: c# asp.net-mvc-5 repository ninject


    【解决方案1】:

    你可以这样吗?

    public partial class PCDataEFContext : DbContext
    {
        public PCDataEFContext()
            : base(Util.GetTheConnectionString())
        { }
    }
    
    public class MyDerivedContext : PCDataEFContext
    {
        public MyDerivedContext()
            : base()
        { }
    }
    
    class Util
    {
        public static string GetTheConnectionString()
        {
            // return the correct name based on some logic...
            return "name=PCDataEFContext";
        }
    }
    

    另一种方法是在您定义的 RepositorBase 类中,通过在创建 dbcontext 后更改连接字符串:

        protected D DataContext
        {
            get
            {
                if (dataContext == null)
                {
                    dataContext = new D();
                    dataContext.Database.Connection.ConnectionString = "the new connectionstring";
                }
                return dataContext;
            }
            set { dataContext = value; }
        }
    

    【讨论】:

    • 抱歉,我的评论还没来得及完成就发布了。我的理解是,连接字符串仍将在应用程序启动或实例化时设置。仅当应用程序中需要新存储库时,我将如何设置连接?
    • 如果你想改变一个实例化的dbcontext的连接字符串,你可以用ctxt.Database.Connection.ConnectionString = "new connection string"来做
    • 再次感谢 codemonkey。我的问题是我将在哪里添加这行代码?我不想在我拥有的每个存储库中都这样做。我想在基础存储库或其他一些常见的地方执行此操作。另外,我想将此字符串作为参数传递给存储库,以便我可以在不同时间传递不同的连接字符串。我担心的是这种方法是在运行时有效还是在编译时得到解决?
    • 当您创建 PCDataEFContext 类型的新上下文或基于此类型的任何其他上下文(即在运行时)时,将执行静态函数调用并返回您希望它返回的连接字符串
    • 感谢 codemonkey。我将您的答案标记为已接受。我没有测试你的建议。但我认为这应该有效。我会让你知道结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-15
    • 2012-12-22
    • 1970-01-01
    • 1970-01-01
    • 2019-12-28
    • 2010-11-24
    • 1970-01-01
    相关资源
    最近更新 更多