2016-02-07 99 views
1

我知道有很多關於這個話題的文章,但是無論我在哪裏看,它對我來說都不是太複雜或不清楚。EF - 管理DbContext的最佳方法?

我的團隊首先開發使用Entity框架代碼的Web應用程序。我們也使用Autofac進行依賴注入。

目前,數據訪問如下所示:

提供給那些不包含EF項目的API:

public class DataService 
{ 
    private IDbContextFactory<MyContext> _factory; 
    private IDataServiceExecutor _dataServiceExecutor; 

    public DataService(IDbContextFactory<MyContext> factory, IDataServiceExecutor executor) 
    { 
     _factory = factory; 
     _dataServiceExecutor = executor; 
    } 

    public void AddItem(Product prod) 
    { 
     using (var context = _factory.Create()) 
     { 
      if (_dataServiceExecutor.AddItem(context, prod)) 
       context.SaveChanges(); 
     } 
    } 
} 

我DataServiceExecutor:

public class DataServiceExecutor 
{ 
    private IRepository<Product> _products; 

    public DataService(IRepository<Product> products...more repositories) 
    { 
     _products = products; 
    } 

    public bool AddItem(DbContext context, Prouduct prod) 
    { 
     try 
     { 
      _products.AddItem(context, prod); 

      return true; 
     } 
     catch(Exception ex) 
     { 
      Log(..) 
      return false; 
     } 
    } 
} 

我所有的庫繼承這個抽象存儲庫:

public abstract class EFRepository<T> : IRepository<T> 
{ 
    public void AddItem<T>(DbContext context, T item) 
    { 
     context.Set<T>().Add(item); 
    } 

    . 
    . 
    . 
} 

好事是這樣每個事務使用一個上下文。

不好的一面是我的服務方法和我的存儲庫方法都直接使用上下文。應用程序不是那麼大,所以現在方法注入上下文很好,但它可能會變得更大,所以在我看來,注入當前狀態的上下文是有問題的。它看起來很糟糕。

也許還有更多的優點和缺點,我是不知道的..

有什麼辦法,我不熟悉,使數據訪問更好?

+0

你可能有更好的運氣,詢問在http://codereview.stackexchange.com/ – Brandon

回答

0

DataServiceExecutor(本質上是動詞)總是拼寫設計缺陷。這是一種僞裝成類的方法(Execute...)。這些課程的職責不明確,因爲他們的職能不可避免地屬於其他職位。

與Inversion of Control本身一樣偉大的模式的問題是,IoC容器可用於注入任何依賴項。所以他們可以讓你創建一個依賴關係和分散責任的糾結,並仍然做一個體面的工作來管理生命週期。它們可能會掩蓋你所擁有的生命週期問題。

因此,讓我們暫時忽略IoC,如果您撥打DataServiceExecutor.AddItem,請查看您的代碼在創建簡單對象時的外觀。

var product = new Product(); 
var factory = new DbContextFactory<MyContext>(); // Dependencies unknown 
var productRepository = new Repository<Product>(context); 
var executor = new DataServiceExecutor(productRepository); 
var dataService = new DataService(factory, executor); 

dataServiceAddItem方法,你基本上有:

using (var context = _factory.Create()) 
{ 
    executor.AddItem(context, product); 
    context.SaveChanges(); 
} 

如果DataService會收到productRepository代替executor,這一切歸結爲:

productRepository.AddItem(context, product); 
context.SaveChanges(); 

executor可以取出來容易。它唯一的作用似乎是錯誤記錄。但是,這也可以通過DataService來完成。

但是我們還沒有完成。正如你自己所表明的那樣,以上下文爲參數的這些方法有點尷尬。但現在DataServiceExecutor是出來的圖片,它更自然的事:

var product = new Product(); 
var factory = new DbContextFactory<MyContext>(); 
using (var context = _factory.Create()) 
{ 
    var productRepository = new Repository<Product>(context); 
    productRepository.AddItem(product); 

    // And for example 
    var orderRepository = new Repository<Order>(context); 
    orderRepository.AddItem(order); 

    // One SaveChanges call! 
    context.SaveChanges(); 
} 

而且DataService消失了。

現在EFRepository存儲其context作爲成員變量,並AddItem看起來是這樣的:

public void AddItem<T>(T item) 
{ 
    _context.Set<T>().Add(item); 
} 

現在回到國際奧委會。

在國際奧委會的光,你的代碼的主要問題是這裏面DataService.AddItem

using (var context = _factory.Create()) 

您創建不是由IoC容器管理的環境。它的使用壽命範圍僅限於AddItem方法。因此,您必須將其傳遞到各地,以確保業務事務中的所有內容都使用這一個實例。通過將存儲庫的依賴關係(上下文)返回給構造器注入,讓IoC容器管理上下文的生命週期變得更加容易。

順便說一句,你說DataService是「供給不包含EF項目API」的一部分。但它在其通用參數中引用MyContext。也許MyContext也是抽象的,我不知道。無論如何,你也可以通過IoC提供這種抽象的實例。

+0

感謝您的詳細答案!首先,該服務的確提供了API,Autofac將注入上下文工廠。其次,執行者的目的在於實際執行操作,如果操作成功和/或處理上下文,則服務責任是保存更改。我知道它是醜陋傳遞上下文,但不知道如何使用依賴注入,以防止它,但保持相同的上下文中每筆交易,我無法從你的回答瞭解如何注入,要麼 –

+0

可以注入它類似於你如何注入工廠等,也就是說通過構造函數注入。我確信有很多關於如何使用Autofac注入上下文的例子。但它可能會改變你的程序流程。我認爲這是最大的問題。但是,我向您展示的是使用存儲庫和上下文的更常見(和多功能)方法。 –

+0

我再次讀到您的第一條評論,並且所有內容都是如此正確,擺脫執行者是聰明的,並且依賴存儲庫並在其ctor中採用上下文。現在我面臨另一個大問題,那就是如何在我的startApp中實際註冊dbContext對象。它迫使我引用Ef,我真的不喜歡 –

0

我的觀點是解決方案沒有正確分層。我猜DataService是從外部訪問的最高層?

在這種情況下我會改變爲以下:

  • 服務獲取存儲庫(或數據層)通過構造注入(然後適當地處理)。服務方法只需要相關參數。
  • 什麼是數據層用於?它可以被刪除嗎?我通常在擁有所有存儲庫的服務下面有一個數據層。在這種情況下,當服務處理數據層時,數據層可能負責處理所有的存儲庫。
  • 存儲庫可以保持原樣,但應該通過構造函數注入上下文。
+0

Upadated我的問題在這使它更清晰。如果你可以用代碼描述你的答案,也許我會更好地瞭解 –

相關問題