天天看點

DataRabbit 輕量的資料通路架構(02) -- IOrmAccesser

   (完全限定類名:DataRabbit.ORM.IOrmAccesser)   

   在DataRabbit架構中,通過IOrmAccesser來對資料庫進行ORM通路,隻要Entity(即ORM中的“O”)的定義與資料庫表的結構完全一緻,即可使用IOrmAccesser來對其進行ORM操作。

1.Entity

2.Filter

   我們經常需要依據條件來搜尋資料,在DataRabbit的ORM架構中,使用Filter來表示一個單獨的條件。Filter從ColumnItem繼承,ColumnItem 表示資料列及其對應的值。比如,在進行Update操作時,我們可以使用一個ColumnItem 的List來指定要将哪些列的值更新為指定的值。

   首先,注意,Filter中包含一個GetBooleanExpression()方法,該方法将目前Filter轉換為一個标準的Sql條件字句。

   Filter的ComparisonOperator屬性表明了采用何種比較符來建構條件表達式。

DataRabbit 輕量的資料通路架構(02) -- IOrmAccesser
DataRabbit 輕量的資料通路架構(02) -- IOrmAccesser

ComparisonOperators

    [EnumDescription("比較操作符")]

    public enum ComparisonOperators

    {

        [EnumDescription("=")]

        Equal ,

        [EnumDescription("!=")]

        NotEqual ,

        [EnumDescription(">")]

        Greater ,

        [EnumDescription("<")]

        Less ,

        [EnumDescription(">=")]

        NotLessThan,

        [EnumDescription("<=")]

        NotGreaterThan,

        [EnumDescription(" like ")]

        Like

    }

   在IOrmAccesser接口中,很多方法都接受 params Filter[] conditions 或IList<Filter>參數,比如:

        void Delete(IList<Filter> conditions);

        void Delete(params Filter[] conditions);

   比如,要删除資料庫Student表中所有Age大于20歲且為男性的學生記錄

 stuOrmAccesser.Delete(new Filter(Student._Age, 20, ComparisonOperators.Greater), new Filter(Student._IsBoy, true, ComparisonOperators.Equal));

   針對接受 params Filter[] conditions 或IList<Filter>參數的方法,在OrmAccesser内部将會對每個Filter所表示的單個條件進行“與”操作,來作為搜尋條件。那麼如果需要對各個Filter進行“或”操作,或進行更複雜的邏輯組合(如“filter1 && (filter2 || filter3)”),就需要采用對應的接受IFilterTree作為參數的重載方法。

3.IFilterTree

   IFilterTree 用于表示多個Filter的邏輯組合。

   注意,IFilterTree中也包含一個GetBooleanExpression()方法,該方法将目前Filter通過邏輯組合轉換為一個标準的Sql條件字句。

   目前的IFilterTree有兩個預設實作:

(1)SimpleFilterTree

   該實作僅僅支援最簡單的對多個條件都進行“與”或都進行“或”的邏輯操作,更複雜的邏輯組合需求,可以使用AgileFilterTree。

   如果将上述的例子,改用IFilterTree可以這樣實作:

            IList<Filter> conditions = new List<Filter>();

            conditions.Add(new Filter(Student._Age, 20, ComparisonOperators.Greater));

            conditions.Add(new Filter(Student._IsBoy, true, ComparisonOperators.Equal));

            IFilterTree conditionTree = new SimpleFilterTree(LogicType.And, conditions);

            stuOrmAccesser.Delete(conditionTree);

(2)AgileFilterTree

   AgileFilterTree 可以表示非常複雜的多個Filter的邏輯組合。它使用一個logicExpression字元串描述邏輯組合表達式,如"filter1 && (filter2 || filter3)",然後解析這個表達式擷取正确的Sql條件語句。

   比如,我們要找出所有年齡在20與25歲之間,或者名字為sky的學生:

            IDictionary<string, Filter> mapping = new Dictionary<string, Filter>();

            mapping.Add("A", new Filter(Student._Name, "sky", ComparisonOperators.Equal));

            mapping.Add("B", new Filter(Student._Age, 20, ComparisonOperators.Greater));

            mapping.Add("C", new Filter(Student._Age, 25, ComparisonOperators.Less));

            IFilterTree agileTree = new AgileFilterTree("A||(B&&C)", mapping);

            IList<Student> list = stuOrmAccesser.GetMuch(agileTree);

4.IOrmAccesser的泛型參數

   IOrmAccesser是一個泛型接口,泛型參數是EntityType--即實體的類型,我們知道,每個EntityType對應着資料庫中的一個表,Entity class的名字最好與資料表的名字一緻,這樣IOrmAccesser就可以根據EntityType知道要通路資料庫中的哪個表。如果Entity class的名字最好與資料表的名字不一緻,也沒關系,我們可以通過向IDataAccesser的OrmCoagent屬性注入IOrmCoagent來提供EntityType與資料表名稱的映射關系。IOrmCoagent接口定義如下:

    public interface IOrmCoagent

        /// <summary>

        /// GetTableName 根據Entity類型擷取對應的資料庫表名

        /// </summary>        

        string GetTableName(Type entityType);

   IOrmAccesser可以通過IOrmCoagent的GetTableName()方法來擷取EntityType所對應的資料庫表的名稱。

5.基本"CRUD"方法

   IOrmAccesser提供了基本的“CRUD”方法,如Insert,Update,Delete,GetOne,GetMuch,GetDataSet等等。這些方法都提供了多個重載,以接收單個Filter條件或多個Filter以及IFilterTree。

   大多數方法的含義都特别清晰明了,有幾個方法的含義需要特别指出一下:

        /// GetMuchWithoutBlob 根據參數conditions來提取符合條件的所有Entity,但是Entity的blob字段沒有被填充。

        IList<EntityType> GetMuchWithoutBlob(params Filter[] conditions);

        /// LoadBlob 填充entity的Blob字段

        void LoadBlob(EntityType entity);

        /// Update 更新符合conditions的記錄中由columnItems指定的各個Column為對應目标值。

        void Update(IList<ColumnItem> columnItems, IList<Filter> conditions);

        /// GetDataSet 選取表中符合條件的row,并且隻傳回columns指定的列。

        /// </summary>      

        DataSet GetDataSet(IList<Filter> conditions, params string[] columns);

6.基于主外鍵關系進行Get擷取

    IOrmAccesser會自動依據資料表的主外鍵關系來進行關系加載,比如,Student表中有MentorID字段(外鍵),對應Mentor表中的主鍵。那麼,IOrmAccesser的GetParent方法,就可以根據指定的Student對象傳回Mentor對象。

Mentor mentor = stuOrmAccesser.GetParent<Mentor>(student);

基于主外鍵關系進行Get的方法包括:

        /// GetParent 依據entity中外鍵的值,擷取主表中的實體。外鍵建立了"語義"上的"Master-Detail"關系

        /// </summary>       

        ParentType GetParent<ParentType>(EntityType entity);

        /// GetForeigner 依據entity中名為fkeyName外鍵的值,擷取主表中的對應實體。外鍵沒有"語義"上的"Master-Detail"關系

        ForeignerType GetForeigner<ForeignerType>(EntityType entity ,string fkeyName);

        /// GetChildList 依據entity中主鍵的值,擷取從表中的所有相關實體

        /// </summary>

        IList<ChildType> GetChildList<ChildType>(EntityType entity);

        /// GetChildDataSet 依據entity中主鍵的值,擷取從表中的所有相關記錄

        DataSet GetChildDataSet<ChildType>(EntityType entity);

        #endregion