c# Entity Framework 什么时候应该使用新的 dbContext?

标签 c# sql database entity-framework design-patterns

有一段时间我想知道创建 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/

相关文章:

python - postgres - 无法使用 psycopg2 删除数据库

mysql - 如何在每个作业结束时在 talend 中实现日志记录?

c# - 无法在 backgroundTask 调用 Task.Run()

c# - C# 中字符串类型的最快(内置)比较是什么

java - 为什么需要数据库代理键的 generatedKeys?

php - SQL 更新/插入循环 $_GET

android - 创建数据库,表并插入数据并在android中检索它

C# 全局键盘钩子(Hook),从控制台应用程序打开一个表单

c# - MonoTouch "unrecognized selector sent to instance"不适用于 iOS5(但适用于 iOS6)

sql - 根据计算值选择,优化