2016-12-27 42 views
3

我想知道一段时间什么是正确的方法来创建一个新的dbcontext实例?我遇到了一些问题,因为当我通过SQL Server弥补数据库中的更改时,我的上下文不会更新数据。让我解释我的网站是如何工作的。c#实体框架何时应该使用新的dbContext?

我们正在为我们的客户做一个预约网站明显预约。我们将托管我们服务器上的所有数据库。如何应用它的工作是由2连接:

第一连接

这方面所有的时间连接到同一个数据库让我们把它的主人。 www.example.com/foo 服务器将检查那里这里是 所以它会查找代码: 这将例如将用户重定向到的URL代码良好的数据库中它桌上对决代码,然后以良好的数据库名称,它应该重定向和它在这里是我的第二个连接来的最高

第二个连接

这人会根据做出正确的数据库连接主人已经返回的数据。从这里开始,似乎所有的工作都很好,除了DBContext实际上从来没有更新过,因为我没有正确实例化它,而且我也没有很好的经验。下面是我与我的同事代码:

using System; 
using System.Data.EntityClient; 
using System.Data.SqlClient; 
using System.Linq; 
using System.Threading; 
using System.Web; 
using System.Web.Routing; 
using WebRV.Models.Entities; 

namespace WebRV.RouteDb 
{ 

    public class DbConnection 
    { 

     private static DbConnection instance; 
     private Cliniciel_WebRV_Entities db; 
     private String connectionString; 
     private readonly Cliniciel_WebRV_MasterEntities masterDb = new Cliniciel_WebRV_MasterEntities(); 
     private Int32 idCie; 
     private static readonly object myLock = new object(); 


     private DbConnection() { 
      var context = new HttpContextWrapper(System.Web.HttpContext.Current); 
      var routeData = RouteTable.Routes.GetRouteData(context); 
      // Use RouteData directly: 
      String code = routeData.Values["code"].ToString(); 
      //String code = Thread.CurrentContext. .RequestContext.RouteData.Values["code"].ToString(); 
      var response = masterDb.SYS_tbCustDBLocation.Where(p => p.CustDBLocationCode == code).ToList(); 

      if (response.Count == 1) 
      { 
       try 
       { 
        db = CreateConnection(response.FirstOrDefault()); 
        idCie = (db.SYS_vwCie.Where(p => p.ClinicielWebName == code).FirstOrDefault()).IdCie; 
       } 
       catch (Exception e) 
       { 
        throw e; 
       } 

      } 
      else { 
       throw new FormatException(); 
      } 
     } 

     private Cliniciel_WebRV_Entities CreateConnection(SYS_tbCustDBLocation data) 
     { 

      connectionString = ***** 

      db = new Cliniciel_WebRV_Entities(); 

      db.Database.Connection.ConnectionString = connectionString; 

      db.Database.Connection.Open(); 

      return db; 
     } 

     private static void CreateInstance() { 
      instance = new DbConnection(); 
     } 

     public static DbConnection GetInstance() { 
      lock (myLock) 
      { 
       if (instance == null) 
       { 
        CreateInstance(); 
       } 

      } 

      return instance; 
     } 

     public String GetConnectionString() 
     { 
      return connectionString; 
     } 

     public Cliniciel_WebRV_Entities GetConnection() 
     { 
      return db; 
     } 

     public Int32 GetIdCie() 
     { 
      //hard code 1 but test 
      //return idCie; 
      return 1; 
     } 

    } 
} 

,这里是我如何使用它的一个例子:

//[CompanyCodeFilter] 
    public class HomeController : AppointementController 
    { 
     //public static Cliniciel_WebRV_Entities entityDB = DbConnection.GetConnection(); 

     public HomeController() 
     { 
      base.Refresh(); 
     } 

public JsonResult GetConsultationDescription(Int32 idService) 
     { 
      //base.Refresh(); 
      entityDB.Set<SYS_vwService>().AsNoTracking(); 
      var motifDescription = entityDB.SYS_vwService.Where(s => s.IDLang == cultureName && s.IdService == idService && s.IdCie == idCie).FirstOrDefault(); 
      var base64 = Convert.ToBase64String(motifDescription.ServiceImage); 
      var imgSrc = String.Format("data:image/gif;base64,{0}", base64); 
      var imageDecode = imgSrc; 
      if (base64 == "AA==") 
      { 
       imageDecode = ""; 
      } 
      var result = new { motifDescription, imageDecode }; 


      return Json(result, JsonRequestBehavior.AllowGet); 
     } 
    } 

这里base.refresh()调用此:

using System; 
using System.Linq; 
using WebRV.Filters; 
using WebRV.Localization; 
using WebRV.Models.Entities; 
using WebRV.RouteDb; 

namespace WebRV.Controllers 
{ 
    //[CompanyCodeFilter] 
    public class AppointementController : BaseController 
    { 
     protected Cliniciel_WebRV_Entities entityDB; 
     protected Int32 idCie; 
     protected String cultureName; 

     //public AppointementController() { 
     // Refresh(); 
     //} 

     //Permet de bien vérifier quel DB utilisé, quel idCie et quel cultureName. 
     protected void Refresh() { 
      entityDB = DbConnection.GetInstance().GetConnection(); 
      idCie= DbConnection.GetInstance().GetIdCie(); 
      cultureName = CultureLocalization.GetCulture(); 
      //cultureName = "en-ca"; 
     } 

    } 
} 

如果有人可以帮助我正确地实例化连接它会很感激谢谢

+0

您是否收到任何具体的错误你正在试图解决? – Vinod

回答

2

我认为你需要更好地理解h数据库上下文的工作原理。

它是许多设计模式的组合,但在基本层面上,它本质上是一个工作单元,用于跟踪对表示数据的对象的更改。正因为如此,它并不意味着被用作一直保持开放的连接,而且您可以前后一步,尽管您可以在某种程度上像这样使用它。

从您的代码中,它看起来像您在ASP.NET MVC应用程序中使用它。由于应用程序的性质,你可以做两件事情之一:

  • 您可以创建数据库背景下,当您需要使用它,或者
  • 您可以创建数据库上下文的属性控制器

最后,它们有些达到同样的事情。我个人建议您在需要使用时创建上下文的实例,并确保正确处理它。然后,您可以拥有一个基本控制器类,该类会公开一个CreateConnetion()方法,该方法为您的上下文创建一个实例,类似于您已拥有的Cliniciel_WebRV_Entities CreateConnection()方法,不同之处在于您不需要显式打开连接并且可以传递连接字符串作为构造函数参数,如果您添加一个部分类并为上下文实现一个。事情是这样的:

public partial class Cliniciel_WebRV_Entities 
{ 
    public Cliniciel_WebRV_Entities(string nameOrConnectionString):base(nameOrConnectionString) 
    { 

    } 
} 

然后,您可以使用它像这样:

private Cliniciel_WebRV_Entities CreateConnection() 
    { 
     //Code to figure out which db to connect to (based on the other connection. You should consider caching that too if it doesn't change very often) 
     var nameOrConnectionString = FigureOutConnection(); 
     var db = new Cliniciel_WebRV_Entities(nameOrConnectionString); 
     return db; 
    } 

请记住,上下文依赖于元数据,所以请确保您连接字符串反映。

在您的代码,那么您需要使用它是这样的:

public JsonResult GetConsultationDescription(Int32 idService) 
     { 
      using(var entityDB = CreateConnection()) 
      { 
       var motifDescription = entityDB.SYS_vwService.Where(s => s.IDLang == cultureName && s.IdService == idService && s.IdCie == idCie).FirstOrDefault(); 
       var base64 = Convert.ToBase64String(motifDescription.ServiceImage); 
       var imgSrc = String.Format("data:image/gif;base64,{0}", base64); 
       var imageDecode = imgSrc; 
       if (base64 == "AA==") 
       { 
        imageDecode = ""; 
       } 
       var result = new { motifDescription, imageDecode }; 


       return Json(result, JsonRequestBehavior.AllowGet); 
      } 
     } 
    } 

咬伤每一个新人的是,你不应该通过实体(从上下文对象)的意见的另一件事要记住什么东西楷模。这是因为一旦上下文被处理,具有导航属性的对象就会中断。有办法解决,但不推荐。改为将对象映射到模型。

顺便说一句,不要忘记在修改实体后调用SaveChanges()方法,否则数据库将不会随更改而更新。

+0

谢谢你明确的答案胡安我会尝试 – alexandre

0

当你传递的DbContext维修或商务舱,你把它作为一个值不作为参考,所以你会失去在客户端代码中所做的所有更改,选项是将它作为参考传递,但它不是一个安全的,也不是一个好的做法,但是,如果您将该上下文作为委托传递给您,直接传递对象的引用,因此它是最好的选择ch以便保持注入的上下文与来自业务/服务层的更改。 这里的理念是:
选项1,把它作为参考,不建议:

public void Call() 
    { 
     //Attach changes to context, Passing as reference 
     Process(ref _context); 
     //All changes attached to context 
     _context.SaveChanges(); 
    } 

    public void Process(ref Cliniciel_WebRV_MasterEntities context) 
    { 
     var c = context(); 
     //Get entites dbcontext 
     //Update entites 
    } 

选项2,把它作为一个代表,最好计算策略:

public void Call() 
    { 
     //Attach changes to context, Passing as reference 
     Process(() => _context); 
     //All changes attached to context 
     _context.SaveChanges(); 
    } 

    public void Process(Func<Cliniciel_WebRV_MasterEntities> context) 
    { 
     var c = context(); 
     //Get entites dbcontext 
     //Update entites 
    }