(完全限定類名: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屬性表明了采用何種比較符來建構條件表達式。
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