2010-09-10 56 views
4

如果我有下面的代碼,用IoC代替它的最佳實踐/設計認證(我們正在使用Castle Windsor)。由於「using」語句負責創建連接對象,因此不能直接將其注入到構造函數或方法中。 注:使用SQL連接,這似乎是一個乾淨的例子,這裏的主要好處是嘲諷/單元測試用IoC代替以下代碼(Castle Windsor)

public void CustomerRespository 
{ 
    .... 
    public void Save(Customer customer) 
    { 
     using (var cn = new SqlConnection(connectionString)) 
     { 
      using (var cm = new SqlCommand(commandString, cn)) 
      { 
       .... 
       cn.Open(); 
       cm.ExecuteNonQuery(); 
      } 
     } 
    } 
} 

我相信會有至少有幾個選擇,但我們纔剛剛開始我不相信他們不會在以後和/或面對IoC概念時引發我們的問題。我最喜歡的方法將會如下修改方法,任何人都可以突出顯示它的潛在問題?

public interface IDatabase 
{ 
    IDbConnection Connection(string connectionString); 
    IDbCommand Command(string text, IDbConnection conn); 
} 

public class SqlDB : IDatabase 
{ 
    IDbConnection Connection(string connectionString) 
    { return new SqlConnection(connectionString); } 

    IDbCommand Command(string text, IDbConnection conn) 
    { return new SqlCommand(text, conn); } 
} 

public interface ICustomerRespository 
{ 
    void Save(Customer customer) 
} 

public class CustomerRespository : ICustomerRespository 
{ 
    public IDatabase DB{get; private set;} 

    public CustomerRespository(IDatabase db) 
    { 
     DB = db; 
    } 

    .... 
    public void Save(Customer customer) 
    { 
     using (var cn = DB.Connection(connectionString)) 
     { 
      using (var cm = DB.Command(commandString, cn)) 
      { 
       .... 
       cn.Open(); 
       cm.ExecuteNonQuery(); 
      } 
     } 
    } 
} 
+0

使用var cmd = con.CreateCommand()代替新的SqlCommand(str,cn) – jgauffin 2010-09-10 11:32:42

+0

@ M4N,謝謝用「var」更新。 @JQauffin:好主意,現在讓代碼示例保持不變我會按照「原樣」離開,但會從我提議的IDatabase接口的任何實現者中刪除責任。 – 2010-09-10 11:37:29

回答

1

我已經使用了IoC但不是Castle,儘管它們都是相似的,所以這裏是我對此的看法。

我認爲你是在正確的軌道上 - 雖然我可能使用單獨的工廠進行連接和命令,或者實際上將連接打開和命令運行到另一個類,因此存儲庫不必知道這個細節。只需在類的構造函數中使用IDatabase,以便注入(或者如果您使用基於屬性的注入,則使用屬性)。用IDbConnection和IDbCommand替換代碼中的SqlConnection和SqlCommand。

UPDATE

他們繼承/實現IDisposable所以你可以使用using語句。對不起,我錯了。

+0

@Alistad,我只是看了一下接口的MSDN定義,並說這兩個提到的是從IDisposable繼承的。 http://msdn.microsoft.com/en-us/library/system.data.idbconnection.aspx和http://msdn.microsoft.com/en-us/library/system.data.idbcommand.aspx – 2010-09-10 11:27:34

+0

對不起,我的對象瀏覽器沒有顯示我這個,好笑... – Aliostad 2010-09-10 11:31:12

1

雖然我不會試圖模擬接口IDbConnectionIDbCommand,但由於這可能很複雜,並且更重要的是不會告訴您代碼是否按預期工作,所以一般方法對我來說似乎很好。

它可以讓你改變你使用的數據庫,所以你可以使用類似Sqlite的東西進行單元測試,然後在集成測試期間針對生產數據庫測試代碼。

您也可以將連接字符串移動到IDatabase抽象,這將簡化客戶端。

+0

好主意,以清理連接字符串,我會保持原樣,以保持示例代碼的合理長度。使用Moq我不打算模擬整個IDbConnection或存儲庫,只是與測試相關的位(即超時或不可用)。 – 2010-09-10 13:35:59