基于.NET的SQL条件对象
一直想把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});
}
}
新的一年开始了在这里祝大家:心想事成、身体健康、人人有工开、年年揾大银!