存取庫(Repositories)II - How To

物件狀態的保存,牽涉到資料的持續性,應用系統透過資料庫管理資料,這一部份必須與領域層切割,讓資料庫的存取作業獨立於領域模型之外,因此我們透過建立存取庫(Repository)集中管理相關的功能,便於後續的系統發展,保留擴充與修改的彈性。

Repository負責最後與底層資料庫的溝通,實作資料存取作業所需的功能,在商業軟體的開發上,一般Repository會定義一組方法,透過底層資料庫的連結,支援資料的增刪改查等作業,底下的程式碼以商品資料的 Repository 為例:
public class ProductRepository : IProductRepository
{
    
    public int Create(Product product)
    {
        // 建立新商品資料
    }
    public int Delete(int id)
    {
        // 根據 id 刪除指定的商品
    }
    public List FindAll()
    {
        // 取得所有的商品資料
    }
    public Product FindByID(int id)
    {
        // 根據 id 取得定的商品
    }
    public int Update(Product product)
    {
        // 根據傳入的 Product 實體,更新商品資料
    }
}
其中的方法成員組成,是典型的Repository設計,外部程序根據方法定義傳入所需的參數,完成相關的資料存取操作,在需要的時候,取得封裝資料的物件回傳,或是將實體封裝資料傳入相關的方法完成資料更新異動作業。

在實作上,我們必須另外提供開放介面以支援Repository物件的執行期注入,也因此這個 ProductRepository 類別的方法成員,經由實作 IProductRepository 介面配置,以遵守領域層實作的規格定義,同時避免取用 Respository 的客戶端程式產生耦合,以下是這個類別的介面規格:
public interface IProductRepository
{
    List FindAll();
    Product FindByID(int id);
    int Create(Product product);
    int Update(Product product);
    int Delete(int id);
}
Repository負責維護物件的持續狀態,與底層資料來源(一般是關聯式資料庫)連線,直接溝通,因此我們將其配置於基礎架構層,與領域層切開,如此一來,開發人員可以在不影響領域層並維持介面規格的前提下,根據需求進行抽換。

以下是 Repository 在分層架構設計上的配置。



介面僅定義規格,配置於領域層,在執行期根據規格定義注入實作物件,Repository在基礎架構層中,配合資料來源需要進行抽換或是調整,透過如此的設計,我們因此可以建立具擴充彈性的資料存取架構,在不影響領域層情形下進行調整。

Repository 實作 – 比較 ADO.NET 與 Entity Framework

Repository 與底層資料來源溝通,直觀上我們參考資料庫結構為基礎設計 Repository ,以常見的訂單系統為例,在資料庫中至少需要三個資料表,分別是Order、OrderLine以及Product,因此我們設計三個對應的Repository,並且為了方便識別,以資料表名稱作字首,對應如下表:

資料表Repository
ProductProductRepository
OrderOrderRepository
OrderLineOrderLineRepository

當系統比較單純的時候,對應設計可以應付資料維護的問題,而商業系統通常涵蓋了數以百千計的資料表,一對一的設計,除了大量的類別定義,由於資料表彼此的關聯架構,例如針對某 Order資料的刪除調整,必須考慮其下的OrderLine等等,在資料編輯的維護上,將會產生很大的困難。

ADO.NET直接透過SQL敘述,支援資料的維護操作,開發人員在取得資料物件之後,必須進一步完成實體的轉換建立與關聯設計的維護作業。



圖示說明ADO.NET的Repository實作過程,針對每一個資料表,透過SQL存取DataSet,並且進一步架構Repository定義,可以想像在大型系統的開發,這會是一個難辛的過程,而現在我們有了Entity Framework,透過其內建的設計支援,可以為開發人員省下不少力氣。



以上述的ADO.NET 設計流程作比較,經由實體對應檔,開發人員只要專注在實體定義,並透過物件查詢語言LINQ的協助,即可建立所需的Repository定義,同時經由實體屬性自動維護其中的關聯,而Entity Framework會自動根據開發人員設計的LINQ,透過對應檔,維護必要的SQL 指令。

從這裏的說明,除了進一步理解建構Repository所需步驟,同時我們可以發現,Entity Framework更進一步封裝了ADO.NET的功能,並為開發人員維護實體與底層資料來源的對應,大幅降低了領域模型開發的困難度。





沒有留言: