使用操作符重載,生成ORM實體類的SQL條件語句


ORM框架的一個不可或缺的功能就是根據實體類,生成操作數據庫的SQL語句,這其中,最難處理的就是那些復雜的SQL條件比較語句。比如,有下面這樣一個SQL語句:

 

SELECT  [ id ], [ BankCode ], [ CityCode ], [ FundCode ], [ FundName ], [ FundReviews ], [ EndDagte ], [ addDate ]
  FROM  [ FundReviews ]
     WHERE  ( 
             ( [ CityCode ] = @CP1  OR  [ BankCode ] = @CP2)  
         AND  ( [ FundCode ] = @CP3  OR  [ BankCode ] = @CP4
           )

這個復雜的查詢條件由兩個OR子條件最后組合成一個AND 條件的,因此它有3組條件:

1:[CityCode]=@CP1 OR [BankCode]=@CP2;

2:[FundCode]=@CP3 OR [BankCode]=@CP4;

3:1 AND 2 ;

而條件1其實就是 Condition1 OR Condition2,這又是一個條件組合。

我們發現,盡管SQL的條件語句可能很復雜,但這些條件卻是由一些子條件組合成的,或者說由一組條件組合成一個新的條件,大家想想,這是不是典型的“組合模式”阿?

 

在PDF.NET框架的ORM組件中,有一個專門處理條件的對象OQLCompare ,它就是根據“組合模式”設計的,我們來看看怎么由它來構造這個查詢條件:

1,采用AND,OR重載:

 

FundReviews p =  new FundReviews(); // 實例化一個實體類
OQL q =  new OQL(p);                // 實例化一個OQL對象
Console.WriteLine( " OQLCompare 復雜比較條件表達式測試--------- ");

OQLCompare cmp =  new OQLCompare(p);
OQLCompare cmpResult = (cmp.Comparer(p.CityCode, OQLCompare.CompareType.Equal,  " 021 ")
                | cmp.Comparer(p.BankCode, OQLCompare.CompareType.Equal,  " 008 "))
                & (cmp.Comparer(p.FundCode, OQLCompare.CompareType.Equal,  " KF008 ")
                | cmp.Comparer(p.BankCode, OQLCompare.CompareType.Equal,  " 008 "));
           

q.Select().Where(cmpResult);

Console.WriteLine( " SQL= " + q.ToString());

 

在OQL中,采用了類似SQL的語法,也是

 

Select( [ 屬性列表 ]). Where( [ 條件表達式 ]).OrderBy( [ 排序字段 ]).GroupBy( [ 分組字段 ]

 

其中[條件表達式]就可以使用OQLCompare對象來構造。由於OQLCompare對象Comparer函數返回的仍然是一個OQLCompare對象,所以可以利用這個特點,采用組合模式,構造出非常復雜的SQL條件語句。

 

我們看到OQL采用了類似函數式的語法風格,但在[條件表達式]的構造過程中,還是顯得很冗長,我們可以繼續對OQLCompare對象進行重構:

 

      ///   <summary>
        
///  設置等於某個實體屬性的比較條件
        
///   </summary>
        
///   <param name="compare"> 當前實體比較對象 </param>
        
///   <param name="Value"> 要比較的值 </param>
        
///   <returns> 構造的實體比較對象 </returns>
         public  static OQLCompare  operator ==(OQLCompare compare,  object Value)
        {
             return BuildOperator(compare, Value,  "  =  ");
        }

         ///   <summary>
        
///  設置不等於某個實體屬性的比較條件
        
///   </summary>
        
///   <param name="compare"> 當前實體比較對象 </param>
        
///   <param name="Value"> 要比較的值 </param>
        
///   <returns> 構造的實體比較對象 </returns>
         public  static OQLCompare  operator !=(OQLCompare compare,  object Value)
        {
             return BuildOperator(compare, Value,  "  <>  ");
        }

      ///   <summary>
        
///  根據實體對象的屬性,獲取新的條件比較對象
        
///   </summary>
        
///   <param name="field"></param>
        
///   <returns></returns>
         public OQLCompare Property( object field)
        {
            OQLCompare cmp =  new OQLCompare();
            cmp.CompareString =  this.currPropName ;
             return cmp;
        }

         private  static OQLCompare BuildOperator(OQLCompare compare,  object Value, string operatorString)
        {
             string paraName = compare.GetNewParameterName();
            compare.CompareString += operatorString + paraName;
            compare.compareValueList.Add(paraName.Substring( 1), Value);
             return compare;
        }

 

我們可以采用類似的方式,繼續實現 >=,>,<=,< 等SQL條件比較符號的重載,這里就不一一舉例了,我們來看新的使用方式:

2,采用SQL比較符號的重載:

 

// 對象 p 為實體類
OQLCompare cmp2 =  new OQLCompare(p);
OQLCompare cmpResult2 = 
               ( cmp2.Property(p.CityCode) ==  " 021 "  | cmp2.Property(p.BankCode) ==  " 008 ")
               &  
               ( cmp2.Property(p.FundCode) ==  " KF008 "| cmp2.Property(p.BankCode) ==  " 008 ");


q.ReSet(); // 重新初始化OQL
q.Select().Where(cmpResult2);

Console.WriteLine( " 操作符重載 SQL= " + q.ToString());

 

 

現在這個SQL條件的構造過程是不是清晰多了?這就是操作符重載的魅力:)

 

3,使用Equal方法,簡化相等比較

直接看下面的代碼,功能跟上面的例子一樣:

 

// 對象 p 為實體類
OQLCompare cmp2 =  new OQLCompare(p);
OQLCompare cmpResult2 = 
               ( cmp2.Equal(p.CityCode, " 021 ")    | cmp2.Equal(p.BankCode, " 008 ")  )
               &  
               ( cmp2.Equal(p.FundCode, " KF008 ")  | cmp2.Equal(p.BankCode, " 008 ")  );

q.ReSet(); // 重新初始化OQL

q.Select().Where(cmpResult2);

Console.WriteLine( " 操作符重載 SQL= " + q.ToString());

從性能上來說,這種方式效率稍高,因為它是函數式的處理方式,更直接。

-------------------------------------------------------------------------

 

注:本文介紹的這個OQL特性僅在PDF.NET Ver 4.3版本受支持,但之前的版本參照本文說的方法加以改進,也可以使用。有關PDF.NET的版本信息,請看官網介紹:
http://www.pwmis.com/sqlmap
有關PDF.NET的開源信息,請參看我的博客文章:

 

節前送禮:PDF.NET(PWMIS數據開發框架)V3.0版開源

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM