2

閱讀Mark Seemann's blog post以及this response其中引用它,我瞭解使用服務定位器模式而不是通過依賴注入通過類構造函數的缺點。我也讀了這個Dependency Injection with Ninject, MVC 3 and using the Service Locator Pattern也討論了這個問題。ASP.NET MVC中的服務定位器替代方案

不過,我的問題是關於這種特殊情況:

public class MyController 
{ 
    public void GetData() 
    { 
     using (var repository = new Repository()) 
     { 
      // Use the repository which disposes of an Entity Framework 
      // data context at the end of its life. 
     } 
    } 

    // Lots of other methods. 
} 

在這裏,我有一個包含一個調用庫自動實例化一個內部實體框架數據上下文的方法的控制器。這個單一的數據上下文被使用,因爲上下文被存儲庫中的每個方法調用,所以在存儲庫對象的整個生命週期中共享一個上下文似乎是有意義的。

現在,由於控制器類很大,所以存在一個更大的機會而不是不會使用此給定的存儲庫。正如我假設(也許不正確),這種實例化DC是一項昂貴的操作,我寧願避免這樣做。使用服務定位器模式允許我推遲實例化,直到實際需要上下文爲止,但在上面的鏈接中針對它的有效參數,我寧願避免它。

所以我想知道的是,如果在上述情況下使用依賴注入的更有效的方式會阻止我不必要地實例化我的存儲庫和底層數據上下文。

+0

這個問題太主觀了。 「更好」是*非常*模糊。 –

+0

我編輯了這個問題,試圖澄清我在問什麼。 –

回答

2

我認爲答案取決於您的存儲庫如何管理連接。如果它在構建時打開了與數據庫的連接,那麼我認爲問題出在你的存儲庫上,而不是依賴注入。您的存儲庫只能在發出請求時打開連接,並在收到響應後儘快關閉它。遵循這種模式,依賴注入仍然有意義。


根據您的更新,你還是最好使用DI因爲EF沒有打開構造時,只有當一個請求時數據庫的連接。您的數據上下文足夠小,以便爲每個請求創建上下文所需的少量開銷。


還有一個評論:你也應該考慮注入您的數據上下文到您的資料庫,並讓你的DI容器控件的背景下的壽命。這允許您在單個請求期間在一個或多個存儲庫中使用相同的上下文。 Here's a pretty good resource explaining how to implement the Repository and Unit of Work patterns with Entity Framework in ASP.NET MVC

+0

我在編寫我的存儲庫時考慮過這個問題,但由於存儲庫中的每個單一方法都使用相同的連接,因此可以方便地將連接的生命期與存儲庫實例的生命週期聯繫起來。有沒有這樣做的好理由? –

+0

如果您的控制器正在ASP.NET MVC中使用,那麼每個方法都不會使用相同的連接,因爲每個請求都會實例化一個新的控制器,從而創建一個新的存儲庫,從而建立一個新的連接。 – sellmeadog

+0

我更新了該問題,並提供了更多信息以迴應您的評論。 –

2

由於控制器類很大,所以不存在連接不會在任何給定構造上使用的可能性,因此使用標準構造函數實例化存儲庫並打開連接是沒有意義的基於DI。

注入Lazy,一個Func,或工廠,而不是:

public class MyController 
{ 
    // Use constructor injection to populate this. 
    private Func<MyRepository> _repository; 

    public void GetData() 
    { 
     using (var repository = _repository()) 
     { 
      // ... 
     } 
    } 
} 

這樣就可以避免直到你需要他們創造的實際情況。

@ sellmeadog的回答也不錯。

+0

如果您不在存儲庫的控制範圍內,我會推薦這種方法。 – sellmeadog

1

你問你是否應該將數據庫連接注入到Repository構造函數中?您可以嘗試使用抽象工廠設計模式注入數據庫連接工廠而不是實際的數據庫連接。

public class MyController 
{ 
    public void GetData() 
    { 
     using (var repository = new Repository(IDatabaseConnectionFactory dbConnFac)) 
     { 
      // Use the repository which disposes of a database connection 
      // at the end of its life. 
     } 
    } 

    // Lots of other methods. 
} 

這樣您就可以獲得依賴注入的好處,同時仍允許存儲庫管理其數據庫連接的生命週期。