2015-02-05 22 views
0

我正在一個asp.net mvc web應用程序上工作。現在我已經創建了多個庫類,例如,我有以下的抽象庫類: -坐在我的存儲庫類和控制器類之間使用相同的上下文對象

public interface ISkillRepository : IDisposable 
{//code goes here.. 

&

public interface IStaffRepository : IDisposable 
{//code goes here 

和模型庫: -

public class SkillRepository : ISkillRepository , IDisposable 
       { 
private SkillManagementEntities context = new SkillManagementEntities(); 
    //code goes here 

&

public class StaffRepository : IStaffRepository , IDisposable 
       { 
        private SkillManagementEntities context = new SkillManagementEntities(); 

現在裏面Ÿ控制器我正在intializing和創建回購如下: -

public class SkillController : Controller 
    { 

     private ISkillRepository skillRepository; 


     public SkillController() : this(new SkillRepository()) {} 

     public SkillController(ISkillRepository repository) 
     { 
      skillRepository = repository; 
     } 

,但目前我得到了我的應用程序中出現以下錯誤:

The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects. 

,問題是,我需要通過回購和控制器傳遞相同的上下文。因此,誰能書於在此: -

  1. 我怎麼可以在一個模型內回購參考使用相同的上下文類另一個回購。例如在Staff倉庫內部參考技能庫?我可以在一個控制器類中引用多個回購,但同時在它們之間傳遞相同的上下文對象,所以如果我發出一個save()它將包裝一個事務內的所有語句。例如insie我skillController引用技能&員工回購使用相同的上下文對象?

感謝

編輯 我創建工作類的以下單位: -

public class UnitOfWork : IDisposable 
    { 
     private SkillManagementEntities context = new SkillManagementEntities(); 
     private SkillRepository skillRepository; 
     private StaffRepository staffRepository; 
     private SecurityRoleRepository securityroleRepository; 
     public SkillRepository SkillRepository 
     { 
      get 
      { 

       if (this.skillRepository == null) 
       { 
        this.skillRepository = new SkillRepository(context); 
       } 
       return skillRepository; 
      } 
     } 

     public StaffRepository StaffRepository 
     { 
      get 
      { 

       if (this.staffRepository == null) 
       { 
        this.staffRepository = new StaffRepository(context); 
       } 
       return staffRepository; 
      } 
     } 
     public SecurityRoleRepository SecurityRoleRepository 
     { 
      get 
      { 

       if (this.staffRepository == null) 
       { 
        this.staffRepository = new SecurityRoleRepository(context); 
       } 
       return securityroleRepository; 
      } 
     } 
     public async Task Save() 
     { 
      await context.SaveChangesAsync(); 
     } 

     private bool disposed = false; 

     protected virtual void Dispose(bool disposing) 
     { 
      if (!this.disposed) 
      { 
       if (disposing) 
       { 
        context.Dispose(); 
       } 
      } 
      this.disposed = true; 
     } 

     public void Dispose() 
     { 
      Dispose(true); 
      GC.SuppressFinalize(this); 
     } 
    } 
} 

,然後我的回購裏面我做了以下內容: -

public class SecurityRoleRepository : ISecurityRoleRepository , IDisposable 
     { 
      private SkillManagementEntities context;// = new SkillManagementEntities(); 

      public SecurityRoleRepository(SkillManagementEntities context) 
      { 
       this.context = context; 

和控制器類我會參考ncing的的UnitOfWork如下: -

public class SecurityRoleController : Controller 
    { 

     private UnitOfWork unitOfWork = new UnitOfWork(); 

     public async Task<ActionResult> Index(string filter = null, int page = 1, int pageSize = 20, string sort = "Name", string sortdir = "ASC") 
     { 

      try 
      { 
       var records = new PagedList<SecurityRole>(); 
       ViewBag.filter = filter; 
       records.Content = await unitOfWork.SecurityRoleRepository.GetSecurityRoleForGrid(filter, page, pageSize, sort, sortdir).ToListAsync(); 

現在我面臨的一個問題是,我怎麼能referecne從另一個回購回購?例如我可以參考SecurityRole回購庫中的技能回購?

編輯決賽 我做了如下步驟: - 1.我安裝

Install-Package Ninject.MVC5 

2。然後,我創建了以下相關性類: - :

public class SkillRepository : ISkillRepository , IDisposable 
      { 
       private SkillManagementEntities context ; 

       private IStaffRepository staffrepo = (IStaffRepository)DependencyResolver.Current.GetService(typeof(IStaffRepository)); 
       public SkillRepository(SkillManagementEntities context) 
       { 
        this.context = context; 
       } 

最後我的操作方法中,我將調用 -

public class YourDependencyResolverClass : IDependencyResolver 
{ 
    private IKernel kernel; 

    public YourDependencyResolverClass() 
    { 
     kernel = new StandardKernel(); 
     AddBindings(); 
    } 

    public object GetService(Type serviceType) 
    { 
     return kernel.TryGet(serviceType); 
    } 
    public IEnumerable<object> GetServices(Type serviceType) 
    { 
     return kernel.GetAll(serviceType); 
    } 


    private void AddBindings() 
    { 
     kernel.Bind<ISkillRepository>().To<SkillRepository>(); 
     kernel.Bind<IStaffRepository>().To<StaffRepository>(); 
     kernel.Bind<ISecurityRoleRepository>().To<SecurityRoleRepository>(); 
     kernel.Bind<ICustomerRepository>().To<CustomerRepository>(); 
     kernel.Bind<ISkillVersionHistoryRepository>().To<SkillVersionHistoryRepository>(); 
    } 
} 
} 

3.now我SkillRepository類,我將引用StaffRepository如下內Uiteofwork類如下: -

public class StaffController : Controller 
    { 
     //private SkillManagementEntities db = new SkillManagementEntities(); 

     UnitOfWork unitofwork = new UnitOfWork(); 




    public async Task<ActionResult> AutoComplete(string term) 
     { 

      var staff = await unitofwork.StaffRepository.GetAllActiveStaff(term).Select(a => new { label = a.SamAccUserName }).ToListAsync(); 

      return Json(staff, JsonRequestBehavior.AllowGet); 

和工作類的團結是: -

public class UnitOfWork : IDisposable 
     { 
      private SkillManagementEntities context = new SkillManagementEntities(); 
      private SkillRepository skillRepository; 
      private StaffRepository staffRepository; 
      private SecurityRoleRepository securityroleRepository; 
      private CustomerRepository customerRepository; 
      private SkillVersionHistoryRepository SVH; 
      public SkillRepository SkillRepository 
      { 
       get 
       { 

        if (this.skillRepository == null) 
        { 
         this.skillRepository = new SkillRepository(context); 
        } 
        return skillRepository; 
       } 
      } 

      public StaffRepository StaffRepository 
      { 
       get 
       { 

        if (this.staffRepository == null) 
        { 
         this.staffRepository = new StaffRepository(context); 
        } 
        return staffRepository; 
       } 
      } 
      public CustomerRepository CustomerRepository 
      { 
       get 
       { 

        if (this.customerRepository == null) 
        { 
         this.customerRepository = new CustomerRepository(context); 
        } 
        return customerRepository; 
       } 
      } 
      public SecurityRoleRepository SecurityRoleRepository 
      { 
       get 
       { 

        if (this.securityroleRepository == null) 
        { 
         this.securityroleRepository = new SecurityRoleRepository(context); 
        } 
        return securityroleRepository; 
       } 
      } 
      public SkillVersionHistoryRepository SkillVersionHistoryRepository 
      { 
       get 
       { 

        if (this.SVH == null) 
        { 
         this.SVH = new SkillVersionHistoryRepository(context); 
        } 
        return SVH; 
       } 
      } 
      public async Task Save() 
      { 
       await context.SaveChangesAsync(); 
      } 

      private bool disposed = false; 

      protected virtual void Dispose(bool disposing) 
      { 
       if (!this.disposed) 
       { 
        if (disposing) 
        { 
         context.Dispose(); 
        } 
       } 
       this.disposed = true; 
      } 

      public void Dispose() 
      { 
       Dispose(true); 
       GC.SuppressFinalize(this); 
      } 
     } 

所以,如果我使用unitefwork和DI的方法可以保證我所有的語句都會在單個數據庫事務中發生變形,那麼你能否提出一些建議? thnaks?

+0

調查依賴注入。任何好的DI容器都應該允許您在請求的生命週期中將類型綁定到實例。我個人使用Ninject,並發現它非常易於使用。但是,有很多選擇;找到最適合你的一個。 – 2015-02-05 20:52:45

+0

@ChrisPratt感謝您的回覆,但我可以使用諸如http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing -the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application在我的情況下? – 2015-02-05 22:40:05

+1

不知道這個全新的問題在哪裏出現問題 - 您在一個本地化的地方創建對象 - 顯然您應該能夠根據需要傳遞對構造函數的引用;或者如果您有循環依賴性,則可以使用「Func 」。 ..(我仍然聲稱DI框架是解決/注入依賴關係的更方便的方式 - 但是對於每個特定情況,手動執行都不是太難)。 – 2015-02-06 00:08:17

回答

2

我們通過使用使用的HttpContext request作用域單身共享方面處理這個問題:

public MyContext GetContext() 
    { 
     if (System.Web.HttpContext.Current.Items["MyScopedContext"] == null) 
     { 
      System.Web.HttpContext.Current.Items["MyScopedContext"] = new MyContext(); 
     } 

     return (MyContext)System.Web.HttpContext.Current.Items["MyScopedContext"]; 
    } 

上下文對象(庫)本身實質上安置工作單元。我上面添加的代碼只是爲您提供了一種在請求中運行的所有代碼之間共享單個存儲庫的方法。如果您的存儲庫類是在Web應用程序的範圍內定義的,則可以用對GetContext()方法的調用替換您的SkillManagementEntities()的直接實例化。

另一方面,如果您的存儲庫是在異構應用程序共享的圖層中定義的,則可能需要從可以根據需要注入的工廠對象獲取上下文。無論哪種方式,每個存儲庫創建一個新的上下文對象是什麼導致你的問題。

+0

ca你adivce更多在此?是否與使用工作單位相同? – 2015-02-05 15:22:48

+0

我編輯了我的上面的答案,以更詳細地解釋。希望能讓你走上正軌。 – esmoore68 2015-02-05 15:40:35

+0

我無法理解我需要在我的應用程序中定義「public MyContext GetContext()」的位置? – 2015-02-05 15:56:17

1

不是答案:這個「使用DI」建議答案有點不同的問題 - OP正在尋找「單元的工作」圖案 - 而基本情況(工作單元的壽命相匹配的請求壽命/控制器)可以很容易地用任何DI框架來解決,管理多個工作單元或工作單元的工作時間更長,更加困難和專用的「工作單元工廠」(sample usage)很可能是解決方案。


通常當你走那麼遠與接口/庫和構造函數依賴注入你有一些依賴注入框架。很有可能你正在使用的一個已經提供了「每個HTTP請求」分辨率,或者允許輕鬆添加一個分辨率。

I.e.如果使用Unity,則生命期管理器會使所有.Resolve調用的相同接口/對象返回給定請求的相同實例。查看更多信息,請參閱DI with Unity MSDN文章。

近似樣本:

container.RegisterType<ISkillRepository, SkillRepository>(); 
container.RegisterType<IOtherRepository, OtherRepository>(); 
container.RegisterType<TheContext, TheContext>(new PerRequestLifetime()); 

與此註冊並假設你已經配置ASP.Net MVC使用統一解決類型時,控制器創建與默認生存註冊將得到必要的依賴關係(新實例),但兩者將共享相同的上下文(假設每個都依賴於通過構造函數或屬性注入的類TheContext)。

+0

感謝您的回覆,我不使用Unity ,,我正在尋找諸如http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using -mvc-4 /實現存儲庫和工作單元模式-asp-net-mvc-應用程序,但在他們使用通用回購的例子中,而在我的情況下,我不這樣做, ,所以我對我如何在應用程序內部實現這個工作單元類感到困惑? – 2015-02-05 15:42:25

+0

@johnG - 我看到 - 編輯我的帖子,以澄清這不是一個你正在尋找的方法(保持非刪除,所以其他人不建議你不想要的相同的路線) – 2015-02-05 16:00:08

+0

感謝您的更新,但我我有點困惑,我怎麼可以在我的情況下實現這一點,目前我有每個倉庫內單獨的上下文對象,,我分配接口到我的控制器類,所以我需要能夠傳遞相同的上下文對象之間在我的控制器內部的不同的倉庫,以及如果我在另一個倉庫裏面引用一個倉庫就能夠引用相同的上下文對象 – 2015-02-05 23:04:26

相關問題