Git.Framework 框架隨手記--ORM條件組合

賀臣發表於2014-05-09

  在上一篇<Git.Framework 框架隨手記--ORM新增操作>中簡單記錄瞭如何對資料進行刪除和修改,其用法都非常簡單,在文章中提到了Where()方法,本文將詳述Where() 等條件函式。

 

  一. SQL 條件分析

    對於SQL每個人應該都很熟悉,這是基礎的基礎,如果沒有使用過SQL的本文可以直接忽略了。先簡單看看一個SQL語句,我們根據SQL語句的規則理解Where()方法

SELECT [ID],[UserName],[PassWord],[UserCode],[RealName],[Email],[Mobile],[Phone],[CreateTime],[CreateIp],[CreateUser],[LoginCount],[Picture],[UpdateTime],[IsDelete],[Status],[DepartNum],[ParentCode],[RoleNum],[Remark]
FROM [JooShowGit].[dbo].[Admin]
WHERE [UserCode]=@UserCode AND [IsDelete]=@IsDelete OR [Phone]=@Phone

    SQL語句中後面起始條件關鍵字必定是WHERE,這個毋庸置疑。如果後面要跟其他的條件我們就可以使用AND 或者 OR 關鍵字將其連線起來。SQL條件語句基本可以歸納為如下

SELECT * FROM TABLE WHERE [表示式] (AND|OR) [表示式] ....

    再看看一個稍微複雜點的SQL語句,程式碼如下

SELECT [ID],[UserName],[PassWord],[UserCode],[RealName],[Email],[Mobile],[Phone],[CreateTime],[CreateIp],[CreateUser],[LoginCount],[Picture],[UpdateTime],[IsDelete],[Status],[DepartNum],[ParentCode],[RoleNum],[Remark]
FROM [JooShowGit].[dbo].[Admin]
WHERE ([UserCode]=@UserCode1 OR [UserCode]=@UserCode2) AND [IsDelete]=@IsDelete

    語句是什麼意思,看官一看就能夠明白,我們看重點部分 ,這個SQL語句使用了 () 運算子, 兩個條件 () 和  [IsDelete]=@IsDelete 使用AND連線的,在()運算子中又是多個單個表示式的組合。

    在看看單個表示式的效果

WHERE [UserCode]=@UserCode AND [IsDelete]=@IsDelete OR [Phone]=@Phone

    表示式可以抽象理解為  欄位 [運算子] 值 這種情況。在SQL中有很多運算子,這裡我們看看詳細:

+(加)、―(減)、(乘)、(除)、%(取餘)>(大於)<(小於)、= (等於)、>=(大於等於)、<=(小於等於)、<> (不等於)、!=(不等於)、!>(不大於)!<( 不小於)

    當然其他的運算子(AND OR 也稱作運算子),我們先做一些簡單的。

    以上問題說的比較含糊,表述可能不清晰,但是大家應該都能夠明白其大概意思,從以上的比較可以看出其實SQL是有一定規則的。

 

  二. 框架中提供的條件方法

    在做ORM對映的過程中,我們對條件操作的運算子也做了相應的對映,其對映為了一個列舉值

public enum ECondition
    {
        /// <summary>
        /// AND
        /// </summary>
        //And =1 ,

        /// <summary>
        /// OR
        /// </summary>
        //Or =2 ,

        /// <summary>
        /// LIKE
        /// </summary>
        Like = 3,

        /// <summary>
        /// IN
        /// </summary>
        In = 4,

        /// <summary>
        /// 大於 >
        /// </summary>
        Gth = 5,

        /// <summary>
        /// 小於 <
        /// </summary>
        Lth = 6,

        /// <summary>
        /// 等於 =
        /// </summary>
        Eth = 7,

        /// <summary>
        /// 大於等於 >=
        /// </summary>
        Geth = 8,

        /// <summary>
        /// 小於等於 <=
        /// </summary>
        Leth = 9,

        /// <summary>
        /// 不等於 !=
        /// </summary>
        NotEth = 10,

        /// <summary>
        /// Is 關鍵字
        /// </summary>
        Is = 11,

        /// <summary>
        /// Is Not 關鍵字
        /// </summary>
        IsNot = 12,

        /// <summary>
        /// Between AND關鍵字
        /// </summary>
        Between = 13,

        /// <summary>
        /// OR LIKE
        /// </summary>
        OrLike = 14,

        /// <summary>
        /// OR IN
        /// </summary>
        OrIn = 15,

        /// <summary>
        ///  OR 欄位>
        /// </summary>
        OrGth = 16,


        OrLth = 17,

        OrEth = 18,

        OrGeth = 19,

        OrLeth = 20,

        OrNotEth = 21,

        OrIs = 22,

        OrIsNot = 23,

        OrBetween = 24,

        /// <summary>
        /// +=
        /// </summary>
        AddEth=25,

        /// <summary>
        /// -=
        /// </summary>
        SubtractEth=26,

        /// <summary>
        /// *=
        /// </summary>
        MultiplyEth=27,

        /// <summary>
        /// /=
        /// </summary>
        DivideEth=28,

        /// <summary>
        ///  % 
        /// </summary>
        Modulo=29,

        /// <summary>
        /// +
        /// </summary>
        Add=30,

        /// <summary>
        /// -
        /// </summary>
        Subtract = 31,

        /// <summary>
        /// *
        /// </summary>
        Multiply = 32,

        /// <summary>
        /// /
        /// </summary>
        Divide=33
    }
ECondition 運算子列舉

    其中有些列舉值有點奇怪,當時為了配合理解SQL語法,其中在對() 運算的時候採用了特殊的標記,我們會使用特定的方法來代替。

public void Or(string propertyName, ECondition condition);
public void Or(string propertyName, ECondition condition, params object[] values);
public void OrBegin();public void Where(string propertyName, ECondition condition);
public void Where(string propertyName, ECondition condition, params object[] values);
public void WhereBegin();
public void And(string propertyName, ECondition condition);
public void And(string propertyName, ECondition condition, params object[] values);
public void AndBegin();
public void Begin();public void End();

    這個地方有點意思,我們將WHERE,AND,OR三個連線運算子對映成了相應的方法,其中更加奇怪的是有OrBegin(),WhereBegin(),AndBegin(),Begin(),End()幾個方法。上面在分析SQL的時候主要到了() 運算子,這幾個方法就是為了對()特殊優待,當時設計的時候為了更好的理解() ,將()分為了兩部分 ,分別對應 Begin() ,End(); 也就是前 "(" 和 ")" 而其餘的幾個就是對其擴充套件 。

WHERE ([UserCode]=@UserCode1 OR [UserCode]=@UserCode2) AND [IsDelete]=@IsDelete

    其實也就可以立即為 WhereBegin(); ANND();  OR (); END(); 這種呼叫就好比將寫SQL的手法轉化為命令模式。 很多對此不能夠很好的理解,也對此嗤之以鼻,不要緊這只是理解的角度不一樣而已,而且在對WHERE等方法向Lambda表示式轉化的時候強制不能使用複合條件,避免Linq和EF中的太多層次的巢狀導致自己也暈了。 

    對於上面的一些方法我們還做了一些擴充套件,主要擴充套件方法如下:

public static T And<T>(this T entity, Expression<Func<T, bool>> func) where T : BaseEntity;
public static T And<T>(this T entity, string propertyName, ECondition condition) where T : BaseEntity;
public static T And<T>(this T entity, string propertyName, ECondition condition, params object[] values) where T : BaseEntity;
public static T AndBegin<T>(this T entity) where T : BaseEntity;
public static T Begin<T>(this T entity) where T : BaseEntity;
public static T Between<T>(this T entity, string propertyName, object[] items) where T : BaseEntity;
public static T End<T>(this T entity) where T : BaseEntity;
public static T Or<T>(this T entity, Expression<Func<T, bool>> func) where T : BaseEntity;
public static T Or<T>(this T entity, string propertyName, ECondition condition) where T : BaseEntity;
public static T Or<T>(this T entity, string propertyName, ECondition condition, params object[] values) where T : BaseEntity;
public static T OrBegin<T>(this T entity) where T : BaseEntity;
public static T Where<T>(this T entity, Expression<Func<T, bool>> func) where T : BaseEntity;
public static T Where<T>(this T entity, string propertyName, ECondition condition) where T : BaseEntity;
public static T Where<T>(this T entity, string propertyName, ECondition condition, params object[] values) where T : BaseEntity;
public static T WhereBegin<T>(this T entity) where T : BaseEntity;

 

   三. 使用例項

entity.IncludeAll();
entity.Where(a => a.IsDelete == (int)EIsDelete.NotDelete);

    這個條件語句在之前已經解析過了,就是WHERE [IsDelete]= (int)EIsDelete.NotDelete .

entity.IncludeAll();
entity.Where("IsDelete", ECondition.Eth,(int)EIsDelete.NotDelete);

    上面這兩段程式碼其實是等價的,只是後一種是使用Lambda表示式來解析的,最終的結果都一樣。

SELECT t0.[ID],t0.[UserName],t0.[PassWord],t0.[UserCode],t0.[RealName],t0.[Email],t0.[Mobile],t0.[Phone],t0.[CreateTime],t0.[CreateIp],t0.[CreateUser],t0.[LoginCount],t0.[Picture],t0.[UpdateTime],t0.[IsDelete],t0.[Status],t0.[DepartNum],t0.[ParentCode],t0.[RoleNum],t0.[Remark],t1.[RoleName] AS RoleName FROM [dbo].[Admin] AS t0  LEFT JOIN [dbo].[SysRole] AS t1 ON  t0.[RoleNum]=t1.[RoleNum]  WHERE t0.[IsDelete]=@0_t0_ISDelete

     上面的方法呼叫最終生成的SQL如上,我們中重點看WHERE後面的,如果對比起來應該都能夠理解了

DateTime beginTime = ConvertHelper.ToType<DateTime>(begin);
DateTime endTime = ConvertHelper.ToType<DateTime>(end);
entity.And<T_EXECUTEEntity>("execute_start_time", ECondition.Between, beginTime, endTime).And<T_EXECUTEEntity>("execute_end_time", ECondition.IsNot, null); ;

    


作者:情緣
出處:http://www.cnblogs.com/qingyuan/
關於作者:從事倉庫,生產軟體方面的開發,在專案管理以及企業經營方面尋求發展之路
版權宣告:本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連結。
聯絡方式: 個人QQ  821865130 ; 倉儲技術QQ群 88718955,142050808 ;
吉特倉儲管理系統 開源地址: https://github.com/hechenqingyuan/gitwms

 

相關文章