ORM框架的一個不可或缺的功能就是根據實體類,生成操作數據庫的SQL語句,這其中,最難處理的就是那些復雜的SQL條件比較語句。比如,有下面這樣一個SQL語句:
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重載:
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的語法,也是
其中[條件表達式]就可以使用OQLCompare對象來構造。由於OQLCompare對象Comparer函數返回的仍然是一個OQLCompare對象,所以可以利用這個特點,采用組合模式,構造出非常復雜的SQL條件語句。
我們看到OQL采用了類似函數式的語法風格,但在[條件表達式]的構造過程中,還是顯得很冗長,我們可以繼續對OQLCompare對象進行重構:
/// 設置等於某個實體屬性的比較條件
/// </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比較符號的重載:
OQLCompare cmp2 = new OQLCompare(p);
OQLCompare cmpResult2 =
&
q.ReSet(); // 重新初始化OQL
Console.WriteLine( " 操作符重載 SQL= " + q.ToString());
現在這個SQL條件的構造過程是不是清晰多了?這就是操作符重載的魅力:)
3,使用Equal方法,簡化相等比較
直接看下面的代碼,功能跟上面的例子一樣:
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版開源