0
votes

I have an MVC 5 application that uses EF 6 and implements Repository pattern with dependency injection using the DI container Ninject. The connection string for the dbcontext is stored in the Web.config file which the EF Context properly finds. Everything works fine. Lately, I have a requirement that the connection to my DBContext need to be determined at runtime and connect to different databases (but with exactly the same structure). So, I need to change the sql connectionstring part from the entity connectionstring at run-time before the repository is instantiated. I would really appreciate some help in doing it. I am not a DI guru; know just enough Ninject to get my things going.

Here is my Repository Base Interface:

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

My Repository base implementation:

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
}

Interface and implementation for concrete class:

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

My Ninject dependency resolver:

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

and finally, here is my Entity Framework generated 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; }
}

All the above code works great! But as I said in the beginning, I don't know how to inject the connection string into my Repositorybase class at runtime so that I don't have to modify any of my inherited repositories (I have plenty of them). Someone please help.

Babu.

1

1 Answers

0
votes

Could you do it like this?

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

Another way of doing it, could be in the RepositorBase class you defined, by altering the connectionstring after the creation of the dbcontext:

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