title: Using DI with Entity Framework and multiple data contexts in ASP.NET MVC
body: <p>I am wondering, how we can handle a situation, and if I'm going about this the wrong way. We wrote a web application based on one ERP's database schema model. We are using Entity Framework for the system, with the regular dependency injection method. </p>
  
  <p>Now that we have purchased multiple ERP's from other labs, we are trying to allow their data be used on our first original web portal built for our original ERP. As you can imagine, this is rough as the database models and design will not line up with ours. For example something like <code>GetAllAssets()</code> stored procedure returns the complex type and then is bound to the repo level, the service level and onto the view. </p>
  
  <p>What I was thinking is that we could maybe add multiple EDMX (context for databases), then keep everything from the Views to the controllers to the service layer the same. At the service layer, and type params to our classes, and so we could pass the context the current user logged in as, and then in auto mapper add new entries for the new database context calls from Entity Framework, to map to our original code from the service back down to the view.</p>
  
  <p>Is this possible, and or a good idea or bad idea?</p>
  
  <p>Here is a example of a current basic controller we are using with DI style, and I have removed a lot of code for this question's example:</p>
  
  <pre><code>[AuthorizeWithSession]
  public class LocationController : Controller
  {
      private readonly IMProAssetLocationService _mProAssetLocationService;
      private readonly IUIDataService _uiDataService;
  
      public LocationController(IMProAssetLocationService mProAssetLocationService,
          IUIDataService uiDataService)
      {
          _mProAssetLocationService = mProAssetLocationService;
      }
  
      public ActionResult List()
      {
          return View();
      }
  
      public ActionResult List2()
      {
          return View();
      }
  
      public ActionResult GetLocationList([DataSourceRequest]DataSourceRequest request)
      {
          //var result = DepartmentService.GetDepartmentList(SessionHelper.GetCustId());
          var result = _mProAssetLocationService.MProAssetLocationGetLocationByCustID(SessionHelper.GetCustId(), null);
  
          if (result != null &amp;&amp; result.Any())
          {
              return Json(result.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
          }
      }
  }
  </code></pre>
  
  <p>The interface service layer:</p>
  
  <pre><code>public interface IMProAssetLocationService
  {
      IEnumerable&lt;LocationVm&gt; MProAssetLocationGetLocationByCustID(string custId,string id);
      string MProAssetLocationInsertLocation(LocationVm vm);
      void MProAssetLocationDeleteLocationByCustIDAndLocationID(string custId, string locationId);
      void MProAssetLocationUpdateLocationByCustIDAndLocationID(LocationVm vm);
  }
  </code></pre>
  
  <p>The service layer:</p>
  
  <pre><code>public class MProAssetLocationService : LogManager, IMProAssetLocationService
  {
      private readonly IMProAssetLocationRepo _mProAssetLocationRepo;
  
      public MProAssetLocationService(IMProAssetLocationRepo mProAssetLocationRepo)
      {
          _mProAssetLocationRepo = mProAssetLocationRepo;
      }
  
      protected override Type LogPrefix
      {
          get { return this.GetType(); }
      }
  
      public IEnumerable&lt;LocationVm&gt; MProAssetLocationGetLocationByCustID(string custId, string id)
      {
          List&lt;LocationVm&gt; listlocationVm = new List&lt;LocationVm&gt;();
  
          try
          {
              var records = _mProAssetLocationRepo.MProAssetLocationGetLocationByCustID(custId,id);
           }
     }
  </code></pre>
  
  <p>The Interface repo layer:</p>
  
  <pre><code>public interface IMProAssetLocationRepo : IRepository&lt;MProAssetLocation&gt;
  {
      IEnumerable&lt;string&gt; GetMProAssetLocatonByCustId(string custId);
      IEnumerable&lt;string&gt; GetMProAssetLocatonDescriptionByCustId(string custId);
      IEnumerable&lt;LocationView&gt; GetMProAssetLocatonListByCustId(string search, string locationID, string custId);
      IEnumerable&lt;LocationView&gt; MProAssetLocationGetLocationByCustID(string custId, string id);
      string MProAssetLocationInsertLocation(LocationView lv);
      void MProAssetLocationDeleteLocationByCustIDAndLocationID(string custId, string locationId);
  
      void MProAssetLocationUpdateLocationByCustIDAndLoacationID(LocationView lv);
  }
  </code></pre>
  
  <p>The repo layer:</p>
  
  <pre><code>public class CalLocationsRepo : RepositoryBase&lt;CalLocaton&gt;, ICalLocationsRepo
  {
      public CalLocationsRepo(IDbFactory dbFactory)
          : base(dbFactory)
      {
      }
  
      //WHERE CalCodeActive=1 AND CalCodeGroup='OSS' ORDER BY CalCode
      public IEnumerable&lt;string&gt; GetCalLocations(string empID)
      {
          return DbContext.TAM_GetCalLocationsList(empID).ToList();
      }
  }
  </code></pre>
  
  <p>I was thinking of something like using a context type in our system. I know the entity models calls would be named differently based on our different databases using their own stored procedures, but thought at the level prior to the call i check the context to use, then make the call accordingly like so:</p>
  
  <pre><code>public class DBContextRepo&lt;T&gt; : RepositoryBase, IDBContextRepo&lt;T&gt;
  {
      DBContextRepo&lt;T&gt; _typeParameterClass;
  
      public DBContextRepo(IDbFactory dbFactory, DBContextRepo&lt;T&gt; typeParameterClass)
        : base(dbFactory)
      {
          _typeParameterClass = typeParameterClass;
      }
  
      public List&lt;string&gt; GetAllModelsByManufcaturer(string manufacturerName)
      {
          List&lt;string&gt; results = new List&lt;string&gt;();
  
          if (_typeParameterClass.GetType() == typeof(TAM.DataLayer.EntityModels.QuoteWerks1Entities))
          {
              using(var dbContext = DbContextQw)
              {
                  var items = dbContext.Products_OurProducts_Products.Where(p =&gt; p.Manufacturer == manufacturerName).ToList();
  
                  results = items.Select(p =&gt; p.ManufacturerPartNumber).ToList();
              }
          }
          else
          {
              using (var dbContext = DbContext)
              {
                  var items = dbContext.Models.Where(a =&gt; a.Manufacturer.MfrName == manufacturerName);
                  results = items.Select(m =&gt; m.ModelNumber).ToList();
              }
          }
  
          return results;
      }
  }
  </code></pre>
  
  <p>This causes errors and is where im not sure how to handle two DBContext:</p>
  
  <pre><code> public class DbFactory : Disposable, IDbFactory
  {
      private TAMModel _dbContext;
      private QuoteWerks1Entities _dbContextQW;
  
      public TAMModel Init()
      {
          return _dbContext ?? (_dbContext = new TAMModel());
      }
  
      public QuoteWerks1Entities InitQW()
      {
          return _dbContextQW ?? (_dbContextQW = new QuoteWerks1Entities());
      }
      protected override void DisposeCore()
      {
          if (_dbContext != null)
          {
              _dbContext.Dispose();
          }
  
          if (_dbContextQW != null)
          {
              _dbContextQW.Dispose();
          }
      }
  }
  </code></pre>
  
  <p>Once i added the second context, all of my regular code say they do not have a corresponding type  in constructors such as this one:</p>
  
  <pre><code> public class ContractRepo : RepositoryBase&lt;Contract&gt;, IContractRepo
  {
      public ContractRepo(IDbFactory dbFactory)
          : base(dbFactory)
      {
      }
  
  
      public string GetContractIdentifyByCustId(string custId)
      {
          return DbContext.TAM_GetContractIdentifyByCustId(custId).SingleOrDefault();
      }
  
  }
  </code></pre>
  
  <p>Here is the BaseRepo class:</p>
  
  <pre><code>  public class RepositoryBase
  {
      private readonly TAMModel _dataContext;
      private readonly QuoteWerks1Entities _dataContextQW;
      protected IDbFactory DbFactory { get; private set; }
  
      protected TAMModel DbContext
      {
          get
          {
              return _dataContext ?? DbFactory.Init();
          }
      }
  
      protected QuoteWerks1Entities DbContextQw
      {
          get
          {
              return _dataContextQW ?? DbFactory.InitQW();
          }
      }
  
      protected RepositoryBase(IDbFactory dbFactory)
      {
          DbFactory = dbFactory;
      }
  
  }
  
  public abstract class RepositoryBase&lt;T&gt; where T : class
  {
      private readonly TAMModel _dataContext;
      private readonly IDbSet&lt;T&gt; _dbSet;
      private readonly IDbSet&lt;T&gt; _dbSetQW;
      private readonly QuoteWerks1Entities _dataContextQW;
  
      protected IDbFactory DbFactory { get; private set; }
  
      protected TAMModel DbContext
      {
          get
          {
              return _dataContext ?? DbFactory.Init();
          }
      }
  
      protected QuoteWerks1Entities DbContextQW
      {
          get
          {
              return _dataContextQW ?? DbFactory.InitQW();
          }
      }
  
      protected RepositoryBase(IDbFactory dbFactory, T type)
      {
          DbFactory = dbFactory;
          _dbSet = DbContext.Set&lt;T&gt;();
  
          _dbSetQW = DbContextQW.Set&lt;T&gt;();
      }
  
      public virtual void Add(T entity)
      {
          _dbSet.Add(entity);
      }
  
      public virtual void Update(T entity)
      {
          _dbSet.Attach(entity);
          DbContext.Entry(entity).State = EntityState.Modified;
      }
  
      public virtual void Delete(T entity)
      {
          _dbSet.Remove(entity);
      }
  
      public virtual void Delete(Expression&lt;Func&lt;T, bool&gt;&gt; where)
      {
          IEnumerable&lt;T&gt; objects = _dbSet.Where&lt;T&gt;(where);
          foreach (T obj in objects)
          {
              _dbSet.Remove(obj);
          }
      }
  
      public virtual T GetById(int id)
      {
          return _dbSet.Find(id);
      }
  
      public virtual T GetById(string id)
      {
          return _dbSet.Find(id);
      }
  
      public virtual IEnumerable&lt;T&gt; GetAll()
      {
          return _dbSet.ToList();
      }
  
      public virtual IEnumerable&lt;T&gt; GetMany(Expression&lt;Func&lt;T, bool&gt;&gt; where)
      {
          return _dbSet.Where(where).ToList();
      }
  
      public T Get(Expression&lt;Func&lt;T, bool&gt;&gt; where)
      {
          return _dbSet.Where(where).SingleOrDefault();
      }
  
      public virtual IQueryable&lt;T&gt; Query()
      {
          return _dbSet;
      }
  
      public virtual IQueryable&lt;T&gt; Query(Expression&lt;Func&lt;T, bool&gt;&gt; where)
      {
          return _dbSet.Where(where);
      }
  
      public virtual ObjectQuery&lt;U&gt; CreateQuery&lt;U&gt;(string query, ObjectParameter[] parameters)
      {
          return CastAsObjectContext().CreateQuery&lt;U&gt;(query, parameters);
      }
  
      public virtual ObjectQuery&lt;U&gt; CreateQuery&lt;U&gt;(string query)
      {
          return CreateQuery&lt;U&gt;(query, new ObjectParameter[0] { });
      }
  
      public virtual ObjectQuery&lt;DbDataRecord&gt; CreateQuery(string query, ObjectParameter[] parameters)
      {
          return CreateQuery&lt;DbDataRecord&gt;(query, parameters);
      }
  
      public virtual ObjectQuery&lt;DbDataRecord&gt; CreateQuery(string query)
      {
          return CreateQuery&lt;DbDataRecord&gt;(query);
      }
  
      private ObjectContext CastAsObjectContext()
      {
          var oContext = (DbContext as IObjectContextAdapter).ObjectContext;
  
          return oContext;
      }
  
  }
  </code></pre>
  
  <p>The only problem is, how do I set the context on a login when using dependency injection? Will this work, as at the moment I'm still in the process, or am I over complicating it and going about it the wrong way? Thanks in advance.</p>