簡體   English   中英

c#Entity Framework何時應該使用新的dbContext?

[英]c# Entity Framework when should I use an new dbContext?

我想知道一段時間內創建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";
        }

    }
}

如果有人可以幫助我正確地實例化連接,那將非常感謝謝謝

我認為你需要更好地理解db上下文的工作原理。

它是許多設計模式的組合,但在基本層面上,它本質上是一個工作單元,用於跟蹤表示數據的對象的變化。 因此,它並不意味着被用作一直保持打開的連接,你可以只是前后移動,盡管你可以在一定程度上使用它。

從您的代碼中,您似乎在ASP.NET MVC應用程序中使用它。 由於應用程序的性質,您可以執行以下兩項操作之一:

  • 您可以在需要使用它時創建db上下文,或者
  • 您可以將db上下文創建為控制器的屬性

最后,它們有點相同。 我個人會建議您在需要時使用它來創建上下文的實例,確保正確處理它。 然后,您可以使用一個基本控制器類來公開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()方法,否則數據庫不會隨更改一起更新。

當您將DbContext傳遞給服務或業務類時,您將其作為值傳遞而不是作為引用,因此您將丟失在客戶端代碼中所做的所有更改,選項是將其作為引用傳遞但是它不安全而不是好的做法但是,如果您將上下文作為委托傳遞,則直接傳遞對象的引用,以便最好的approch為了保持注入的上下文與業務/服務層的更改。 這是一個想法:
選項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,將其作為代表傳遞,最佳approch:

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
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM