天天看點

[原創].NET 業務架構開發實戰之六 DAL的重構

.NET 業務架構開發實戰之六 DAL的重構

  前言:其實這個系列還是之前的".NET 分布式架構開發實戰 ",之是以改了名字,主要是因為文章的标題帶來了不少的歧義:系列文章中本打算開發一個簡化業務發的流程的Framework,然後用這個Framework再來實戰,開發一個分布式的應用。改了名字。給大家帶來了不便,敬請見諒。

   本篇的議題如下:

   1. 确定DAL的接口的定義。

  系列文章連結:

<a href="http://www.cnblogs.com/yanyangtian/archive/2010/05/24/1742432.html">[原創].NET 分布式架構開發實戰之二 草稿設計</a> <a href="http://www.cnblogs.com/yanyangtian/archive/2010/05/26/1744064.html">[原創].NET 分布式架構開發實戰之三 資料通路深入一點的思考</a> <a href="http://www.cnblogs.com/yanyangtian/archive/2010/05/28/1746334.html">[原創].NET 分布式架構開發實戰之四 建構從理想和實作之間的橋梁(前篇)</a> <a href="http://www.cnblogs.com/yanyangtian/archive/2010/05/31/1747811.html">[原創].NET 分布式架構開發實戰五 Framework改進篇</a> <a href="http://www.cnblogs.com/yanyangtian/archive/2010/06/03/1750444.html">[原創].NET 業務架構開發實戰之六 DAL的重構</a> <a href="http://www.cnblogs.com/yanyangtian/archive/2010/06/07/1752921.html">[原創].NET 業務架構開發實戰之七 業務層初步構想</a> <a href="http://www.cnblogs.com/yanyangtian/archive/2010/06/09/1754426.html">[原創].NET 業務架構開發實戰之八 業務層Mapping的選擇政策</a> <a href="http://www.cnblogs.com/yanyangtian/archive/2010/06/17/1759327.html">[原創].NET 業務架構開發實戰之九 Mapping屬性原理和驗證規則的實作政策</a> <a href="http://www.cnblogs.com/yanyangtian/archive/2010/06/28/1766442.html">[原創].NET 業務架構開發實戰之十 第一階段總結,深入淺出,水到渠成(前篇)</a> <a href="http://www.cnblogs.com/yanyangtian/archive/2010/06/28/1766460.html">[原創].NET 業務架構開發實戰之十 第一階段總結,深入淺出,水到渠成(後篇)</a>

   之前在開發DAL中,提出了一些思想,也設計了一些接口。現在就把DAL的一些設計完善起來。說是“完善”,并不是說把所有的代碼都實作,而是把該定義的接口,方法敲定下來。Richard認為,設計一個架構或者Framework的時候,開始是接口的定義,定義好各層之間互動的接口,然後才是具體代碼的實作。

   因為在設計Framework的時候,首先要考慮這個Framework的使用者是誰,希望他們怎麼樣來使用開發出來的這個Framework。在這裡,Richard很明白:Framework的使用者就是自己公司裡的開發人員。而且還要使得開發的使用盡量的友善,不要到處去配置一些文檔,最好就是把Framework引入進來,稍微配一下就使用。

  在Richard設計的Framework中,就DAL而言,如果希望DAL傳回DataTable,DataReader等給BLL,那麼需要配置的僅僅隻是指明資料庫的連接配接字元串;如果希望DAL傳回的資料實體給BLL,那麼就得把一張張的表映射成為實體,然後讓這些實體繼承IDataEntity接口就行了(生成實體可以用ORM工具,或者自己手寫代碼)。

 Richard思考了之前對DAL的設計,在此他做了一些改進。

   首先就是對于IDataContext的重新設計和了解:之前的設計是定義了IDataContext,然後用不同的方式實作這個接口,如LinqDataContext.Provider就是用Linq的方法來傳回結果(DataResult)。現在Richard認為IDataContext其實就是用來操作資料庫的,是以傳回的結果就應該是操作資料之後的結果,如Update操作就傳回受影響的行數或者是否更新成功。至于是否要把一些額外的資訊包裝傳回給BLL,就不是IDataContext的實作者的事情了。而且Richard還考慮到了需要在一定程度上支援原生的ADO.NET,起碼給ADO.NET預留接口。

   基于此,Richard就把IDataContext定義為一個接口聲明,然後再定義了IDataEntityContext,和IDataTableContext來繼承IDataContext,他們的關系圖如下:

  

[原創].NET 業務架構開發實戰之六 DAL的重構

   其中IDataEntityContext使用Linq和Entity Framework來實作,而IDataTableContext就是用ADO.NET的方式來實作。

    IDataEntityContext接口的和系列文章中定義的一些方法差不多,但是做了修改。其中有一點要提的就是:ICriteria就是所有條件對象要實作的接口(查詢對象也是條件對象的一種)。例如,可以根據相應的條件删除,更新資料。

[原創].NET 業務架構開發實戰之六 DAL的重構
[原創].NET 業務架構開發實戰之六 DAL的重構

代碼

 /// &lt;summary&gt;

    /// 所有的資料實體執行者實作這個借口

    /// &lt;/summary&gt;

    public interface IDataEntityContext:IDataContext

    {

        TEntity Add&lt;TEntity&gt;(TEntity entity) where TEntity : IDataEntity;

        List&lt;TEntity&gt; Add&lt;TEntity&gt;(List&lt;TEntity&gt; entityList) where TEntity : IDataEntity;

        bool Update&lt;TEntity&gt;(TEntity entity) where TEntity : IDataEntity;

        bool Update&lt;TEntity&gt;(List&lt;TEntity&gt; entityList) where TEntity : IDataEntity;

        bool Update(ICriteria condiftion, object value);

        bool Delete&lt;TEntity&gt;(TEntity entity) where TEntity : IDataEntity;

        bool Delete&lt;TEntity&gt;(List&lt;TEntity&gt; entityList) where TEntity : IDataEntity;

        bool Delete(ICriteria condition);

        int GetCount(ICriteria condition);

        List&lt;TEntity&gt; Query&lt;TEntity&gt;(ICriteria condition);

        List&lt;TEntity&gt; Query&lt;TEntity&gt;(ICriteria condition, int pageIndex, int pageSize, ref int entityCount) where TEntity : IDataEntity;

        List&lt;object&gt; Query(ICriteria condiftion);

    }

   另外就是多了一個 List&lt;object&gt; Query(ICriteria condiftion);方法,之是以有這個方法,Richard考慮到,可能開發人員想要直接自己寫SQL語句去執行,如select avg(Count),sum(Name) from Customer...,開發人員可以寫任意的語句,是以傳回一個實體類不現實,就傳回一個List&lt;object&gt;。

   還有一點就是關于查詢對象的改進:以前僅僅隻是定義了查詢對象的接口,現在用ICriteria 接口中定義來條件對象,而且還可以在條件對象聲明是在對資料操作是否采用事務或者緩存。

[原創].NET 業務架構開發實戰之六 DAL的重構
[原創].NET 業務架構開發實戰之六 DAL的重構

    /// 所有的條件對象都要從這個接口繼承

    public interface ICriteria

        string Name { get; set; }

        bool IsCache { get; set; }

        bool IsTransaction { get; set; }

   

  之後Richard又定義了一個IDataProvider,接口,聲明如下 :

[原創].NET 業務架構開發實戰之六 DAL的重構
[原創].NET 業務架構開發實戰之六 DAL的重構

    /// 資料提供者要實作的借口

    public interface IDataProvider

        DataResult&lt;TEntity&gt; Add&lt;TEntity&gt;(TEntity entity) where TEntity : IDataEntity;

        DataResult&lt;TEntity&gt; Add&lt;TEntity&gt;(List&lt;TEntity&gt; entityList) where TEntity : IDataEntity;

        DataResult&lt;TEntity&gt; Update&lt;TEntity&gt;(TEntity entity) where TEntity : IDataEntity;

        DataResult&lt;TEntity&gt; Update&lt;TEntity&gt;(List&lt;TEntity&gt; entityList) where TEntity : IDataEntity;

        DataResult&lt;TEntity&gt; Delete&lt;TEntity&gt;(TEntity entity) where TEntity : IDataEntity;

        DataResult&lt;TEntity&gt; Delete&lt;TEntity&gt;(List&lt;TEntity&gt; entityList) where TEntity : IDataEntity;

        bool Delete(ICriteria condiftion);

        DataResult&lt;TEntity&gt; GetOne&lt;TEntity&gt;(ICriteria condition) where TEntity : IDataEntity;

        DataResult&lt;TEntity&gt; GetList&lt;TEntity&gt;(ICriteria condition) where TEntity : IDataEntity;

        DataResult&lt;TEntity&gt; GetPageData&lt;TEntity&gt;(ICriteria condition, int pageIndex, int pageSize, ref int entityCount) where TEntity : IDataEntity;

        List&lt;object&gt; GetCustomData(ICriteria condiftion);

   之是以要定義這個接口,其實 Richard就是想讓實作了IDataContext的類踏踏實實的去做底層的資料操作,至于資料操作之後的結果以什麼形式給BLL,不用IDataContext的實作者來關心,而是用IDataProvider的實作者來關心。

   在IDataProvider的實作者在底層就是調用了IDataContext的實作者的方法,然後在IDataProvider中,對外提供了一些更加友好和友善使用的方法,最後在BLL中直接依賴的就是IDataProvider,而不是IDataContext。

   另外,對于IDataProvider傳回的DataResult也做了一些修改:如果傳回的是資料實體,即 使用的是IDataEntityContext來提供底層的資料操作,那麼DataResult&lt;TEntity&gt;是沒有問題的;但是如果使用的是IDataTableContext,那麼傳回DataResult&lt;TEntity&gt;就不行了,因為IDataTableContext查詢方法可能傳回的DataTable,或者DataReader.是以,在設計中葉預留了一個接口:讓IDataProvider傳回的結果實作IDataResult接口,那麼ataResult&lt;TEntity&gt;繼承這個接口,主要用來傳回資料實體,如下:

[原創].NET 業務架構開發實戰之六 DAL的重構

  DAL的設計就到這裡,下一篇文章就開始講述對業務層的一些思考。