一直想把SQL的條件陳述式植入到.NET中以對象的方式體現出來,這樣即能提高開發人員編寫效率的同時也減少在編寫過程中發生錯誤的情況.程式在編譯過程就能夠檢測文法上的錯誤,解決SQL語句在拼湊過程容易發生語法錯誤的問題.剛開始做的時候很多方面不盡人意,也有朋友提了不少意見;經過幾次的重構和完善,現在的使用效果感覺相當滿意.有興趣的朋友看完這後請多提意見!
這一功能暫時整合在HFSoft.Data資料群組件中作為查詢功能的一部份,因為編寫這一功能的目的也是為了這個組件更完善.考慮到以後更好地和其他組件整合會單獨抽取出來實現.組件已經實現部分SQL運算子支援;由於C#提供的運算子名稱和SQL的運算子不是完全一致,所以有個別運算子的命名上有所改變;雖然名稱上有差別但完成的功能是一樣的.
運算子參照表:
SQL |
and |
or |
> |
>= |
< |
<= |
= |
<> |
in |
like |
NET |
& |
| |
> |
>= |
< |
<= |
== |
!= |
^ |
* |
&
條件與條件進行並集,等同於SQL的 and 運算子
|
條件與條件進行交集, 等同於SQL的 or 運算子
>
描述欄位大於某個值的集合, 等同於SQL的>運算子
>=
描述欄位大於或等於某個值的集合, 等同於SQL的>=運算子
<
描述欄位小於某個值的集合, 等同於SQL的<運算子
<=
描述欄位小於或等於某個值的集合, 等同於SQL的<=運算子
==
描述欄位等於某個值的集合, 等同於SQL的=運算子
!=
描述欄位不等於某個值的集合, 等同於SQL的<>運算子
^
描述欄位的值是否存在一個集中,等同於SQL的In運算子
*
描述欄位相似於某個值的集合, 等同於SQL的Like運算子
通過組件提供的運算子功能,可以在.NET下完成大部分SQL條件陳述式的編寫。不過一個組件是否好用必須在實際應用中才能體現出來.
功能使用
SQL:
Select * From Orders where OrderID >=10300這是一條非常簡單的SQL查詢語句,通過組件在。NET下調用的效果又是怎樣?
.NET:
System.Collections.IList list = session.List(typeof(Orders), Orders.F_OrderID >10300);
通過組件在。NET下使用變得簡單,你不在需要定義Command,也不用為拼湊SQL語句煩惱。不過在使用之前必須制定規則,關鍵就是Orders.F_OrderID的定義。
實際也不用太擔心Orders.F_OrderID的定義也是非常簡單的:
public class Orders
{
public Orders()
{
//
// TODO: 在此處添加建構函式邏輯
//
}
private static HFSoft.Data.Expressions.ExpOperator F_mOrderID = new HFSoft.Data.Expressions.ExpOperator("OrderID");
public static HFSoft.Data.Expressions.ExpOperator F_OrderID
{
get
{
return F_mOrderID;
}
}
……………….
}
當定義了一個比較對象後,就可以利用這個對象進行不同的運算比較和組合,從而產生更複雜的條件陳述式。
SQL:
Select * from Orders where (OrderID>10300 and OrderID <10350) or OrderID in(10501,10502,10503) 對於這樣的條件陳述式比較對象也能夠很好地勝任。
.NET:
System.Collections.IList list = session.List(typeof(Orders), (Orders.F_OrderID >10300 & Orders.F_OrderID < 10350) | Orders.F_OrderID ^ new object[]{10501,10502,10503});
SQL:
Select * from Orders where EmployeeID =3 and OrderDate >1996-1-1 and OrderDate < 1997-1-1;
.NET:
System.Collections.IList list = session.List(typeof(Orders), Orders.F_EmployeeID == 3 & Orders.F_OrderDate > "1996-1-1" & Orders.F_OrderDate < "1997-1-1");
從應用的案例可以看到條件對象可以提高編寫SQL條件的效率,解決開發人員面對拼湊SQL條件陳述式煩瑣問題。由於對象是基於C#運算子的實現,因此在程式編譯的過程就可以檢測語法錯誤問題,這樣可以進一步減少因為文法問題所帶來的調試工作量;讓開發人員有更多的精力集中的商務邏輯實現上。
實現描述
由開始到現在大概經過三次比較大的改造。
1)SQL查詢語句對象化的實現
主要把SQL的單個條件在C#中以對象的方式體現出來。這次的工作量是最大的,在做之前必須制定規則介面,在介面的基礎上擴充出=,<>,like,in等條件對象。
http://henryfan.cnblogs.com/archive/2005/09/11/234251.aspx
2)條件對象運算子多載&(and),|(or)
這一次是基於第一次的基礎進行的代碼重構和&,|運算子的重載。使用上稍微有所改變但效果不理想,不過這次使我對運算子有了瞭解。
3)運算子轉換類的實現
這次的完善所得到的效果是最令人滿意,代碼的修改遠遠不及頭兩次;原有的代碼沒有任何改變,只是添加了一個運符重載轉換類。轉換類代碼:
public class ExpOperator
{
public ExpOperator(string name)
{
//
// TODO: 在此處添加建構函式邏輯
//
_Name = name;
}
private string _Name;
public string Name
{
get
{
return _Name;
}
}
public static Expression operator ==(ExpOperator a, object b)
{
return Exps.Eq(a._Name,b);
}
public static Expression operator !=(ExpOperator a, object b)
{
return Exps.NotEq(a._Name,b);
}
public static Expression operator >(ExpOperator a, object b)
{
return Exps.Rt(a._Name,b);
}
public static Expression operator <(ExpOperator a, object b)
{
return Exps.Le(a._Name,b);
}
public static Expression operator >=(ExpOperator a, object b)
{
return Exps.RtEq(a._Name,b);
}
public static Expression operator <=(ExpOperator a, object b)
{
return Exps.LeEq(a._Name,b);
}
public static Expression operator *(ExpOperator a, object b)
{
return Exps.Like(a._Name,b);
}
public static Expression operator ^(ExpOperator a, object b)
{
System.Collections.IList lst = b as System.Collections.IList;
if(lst != null )
return Exps.In(a._Name,lst);
return Exps.In(a._Name,new object[]{b});
}
}
下載案例代碼
新的一年開始了在這裡祝大家:心想事成、身體健康、人人有工開、年年揾大銀!