2016-12-27 3 views
3

Мне было интересно какое-то время, как создать новый экземпляр dbcontext? У меня возникли проблемы с этим, потому что, когда я вношу изменения в свою базу данных через SQL Server, мой контекст не обновляет данные. Позвольте мне объяснить, как работает мой сайт.C# Entity Framework, когда я должен использовать новый dbContext?

Мы делаем сайт встречи для нашего клиента, чтобы принять назначение, очевидно. мы будем размещать всю базу данных на нашем сервере. Как это работает это приложение сделано до 2 Подключение:

первое соединение

это соединение подключить все время одной и той же базы данных давайте назовем его мастер. Это будет перенаправлять пользователя на хорошей базе данных с кодом URL-адрес в этом примере: www.example.com/foo сервер будет проверять наличие кода, где здесь находится Foo Так это будет поиск в таблица для Matchup код, а затем взять хорошее имя базы данных, где он должен перенаправлять и это здесь, что мое второе соединение прийти в очередной раз

второе соединение

Это один сделает подключение к правильной базе данных в соответствии с данные, возвращаемые мастером. Отсюда все работает хорошо, за исключением 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 ow контекст db работает.

Это комбинация многих шаблонов проектирования, но на базовом уровне это, по сути, единица работы, которая отслеживает изменения объектов, представляющих данные. Из-за этого он не предназначен для использования как соединение, которое остается открытым все время, и вы можете просто вернуться назад и вперед, хотя вы можете использовать его как-то в определенной степени.

Из вашего кода, похоже, вы используете его в приложении 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

Спасибо за ясный ответ juan, я попробую это – 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, передать его в качестве делегата, лучше всего 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 
    } 
Смежные вопросы