有一段时间我想知道创建 dbcontext 的新实例的正确方法是什么?我遇到了一些问题,因为当我通过 SQL Server 在数据库中进行更改时,我的上下文不会更新数据。让我解释一下我的网站是如何工作的。
我们正在为我们的客户做一个预约网站,显然可以预约。我们将在我们的服务器上托管所有数据库。应用程序如何工作由 2 个连接组成:
第一次连接
这个连接一直连接到同一个数据库,我们称它为 master。 它会使用示例中的 url 代码将用户重定向到良好的数据库: www.example.com/foo 服务器将检查此处为 foo 的代码 所以它会在表中查找以匹配代码,然后在应该重定向的地方获取正确的数据库名称,我的第二个连接就在这里
二次连接
这个会根据master返回的数据连接到正确的数据库。从这里开始,除了实际上从不更新的 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";
}
}
}
如果有人可以帮助我正确实例化连接,将不胜感激,谢谢
最佳答案
我认为您需要更好地了解数据库上下文的工作原理。
它是许多设计模式的组合,但在基本层面上,它本质上是一个工作单元,用于跟踪代表数据的对象的变化。因此,它并不意味着用作始终保持打开状态的连接,您可以来回切换,尽管您可以在一定程度上这样使用它。
从您的代码来看,您似乎是在 ASP.NET MVC 应用程序中使用它。由于应用程序的性质,您可以执行以下两项操作之一:
- 您可以在需要时创建数据库上下文,或者
- 您可以创建数据库上下文作为 Controller 的属性
最后,它们在某种程度上相当于同一件事。我个人建议您在需要使用上下文时创建一个实例,并确保正确处理它。然后,您可以有一个基 Controller 类,它公开一个 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;
}
请记住,上下文取决于元数据,因此请确保您的连接字符串反射(reflect)了这一点。
在您的代码中,您将像这样使用它:
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);
}
}
}
另一件要记住并且让每个新手都头疼的事情是你不应该将实体(上下文中的对象)传递给模型中的 View 。这是因为一旦上下文被释放,具有导航属性的对象就会中断。有很多解决方法,但不推荐。而是将对象映射到模型。
顺便说一句,不要忘记在修改实体后调用SaveChanges()
方法,否则数据库将不会随着更改而更新。
关于c# Entity Framework 什么时候应该使用新的 dbContext?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41347176/