分享
 
 
 

SQL查询语句对象化的实现(C#)

王朝c#·作者佚名  2006-02-01
窄屏简体版  字體: |||超大  

在开发数据库应用的过程难免会编写大量的SQL语句,其中大部份是查询语句;为不同情况编写查询语句是一件很烦琐的事件。用过hibernate或Nhibernate会了解到把SQL查询语句对象化后使用起非常方便和快捷;也大大减少在编写查询SQL语句所带来的错误等问题。

前段时间在编写一个数据处理类的时候同样遇到这个问题,经过一段时间思考和设计现实现了SQL查询语句对象化的功能;在这里我把自己小小的成果共享一下。

在讲解前先看几个例子(数据是SQLServer的Northwind)注意:例子中所涉及的除查询对象化外还包含整个数据处理类的使用,那部分还在设计和完善当中。

1)以上语句是查询订单ID为10264的订单信息

using(HFSoft.Data.IDataSession session = HFSoft.Data.DataSessionFactory.OpenSession())

{

session.Open();

HFSoft.Data.QueryCmd query = new QueryCmd("Orders");

query.Expreesion.Add(new HFSoft.Data.EqExpression("OrderID",10264));

System.Data.DataSet myDS = session.ExecuteDataSet(query.BuilderCmd(session));

}

对象生成的SQL语句:

SELECT * FROM Orders where 1=1 And (OrderID = @OrderID0)

2)以上语句是查询订单ID大于10264并且小于10600的订单信息

using(HFSoft.Data.IDataSession session = HFSoft.Data.DataSessionFactory.OpenSession())

{

session.Open();

HFSoft.Data.QueryCmd query = new QueryCmd("Orders");

query.Expreesion.Add( new HFSoft.Data.LeExpression("OrderID",10264),

new HFSoft.Data.RtExpression("OrderID",10600));

System.Data.DataSet myDS = session.ExecuteDataSet(query.BuilderCmd(session));

}

对象生成的SQL语句:

SELECT * FROM Orders where 1=1 And (OrderID > @OrderID0) And (OrderID < @OrderID1)

4)以上语句是查询订单ID大于10264并且小于10600或编号是10601,10602,10605的订单信息

using(HFSoft.Data.IDataSession session = HFSoft.Data.DataSessionFactory.OpenSession())

{

session.Open();

HFSoft.Data.QueryCmd query = new QueryCmd("Orders");

query.Expreesion.Add( new HFSoft.Data.LeExpression("OrderID",10264),

new HFSoft.Data.RtExpression("OrderID",10600));

query.Expreesion.Add(HFSoft.Data.UintType.Or,new HFSoft.Data.InExpression("OrderID",new int[]{10601,10602,10605}));

System.Data.DataSet myDS = session.ExecuteDataSet(query.BuilderCmd(session)); }

对象生成的SQL语句:

SELECT * FROM Orders where 1=1 And (OrderID > @OrderID0) And (OrderID < @OrderID1) Or (OrderID in (@OrderID20,@OrderID21,@OrderID22))

从上面的例子我们可以看到对不同的条件进行数据查询只是一件很简单的事情,你并不用为不同的查询情况写相应SQL语句。

接下来讲术这个查询对象实现,对象的最终就是把不同字符串并起来生成相应的SQL语句;SQL语句查询语句主要分为以下几大部份:获取的字段,表名称,条件,排序,分组;了解SELECT语句的对查询语句的组成部分比较了解。

其中比较难的就是条件部分处理,因为条件的组合是情况是比较多;所以设计起来相对比较复杂。在设计的过程中把条件单独抽取出来,并生成接口对条件的表达式进行描述:

/// <summary>

/// 表达式描述接口

/// 用于SQL语句条件表达式的描述

/// </summary>

public interface IExpression

{

/// <summary>

/// 获取表达式

/// </summary>

/// <param name="driver">数据处理设备提供者</param>

/// <returns>string</returns>

string GetFilter(HFSoft.Data.IDriverType driver);

/// <summary>

/// 获取表达式相关的参数

/// </summary>

/// <param name="driver">数据处理设备提供者</param>

/// <returns>System.Data.IDataParameter[]</returns>

System.Data.IDataParameter[] GetDataParams(HFSoft.Data.IDriverType driver);

/// <summary>

/// 序列标识

/// 本属性用于内部处理

/// </summary>

string Sequence

{

get;

set;

}

/// <summary>

/// 添加表达式

/// </summary>

/// <param name="unittype">合并类型(or|and)</param>

/// <param name="expressions">表达式对象</param>

void Add(UintType unittype,params IExpression[] expressions );

/// <summary>

/// 添加表达式

/// </summary>

/// <param name="expressions">表达式对象</param>

void Add(params IExpression[] expressions );

}

在接口描述中有很多地方离不开HFSoft.Data.IDriverType它是用于描述数据库类型。根据HFSoft.Data.IDriverType 对应生成SqlServer,MySql,Oracle等数据库的条件表达式。

为什么IExpression具有Add方法,并且添加的对象也是IExpression;因为条件自己可以包含多个子表达式,只有这样才能够灵活组合成复杂的条件表达式。

接下来看下基于这个接口的实现 /// <summary>

/// 表达式基础类

/// </summary>

[Serializable]

public class Expression:IExpression

{

private string mName;

/// <summary>

/// 获取或设置相关的字段名

/// </summary>

public string Name

{

get

{

return mName;

}

set

{

mName = value;

}

}

private object mValue;

/// <summary>

/// 获取或设置相关的字段值

/// </summary>

public object Value

{

get

{

return mValue;

}

set

{

mValue = value;

}

}

private string mSequence = "";

/// <summary>

/// 获取或设置相关标识

/// 本属性用于内部处理

/// </summary>

public string Sequence

{

get

{

return mSequence;

}

set

{

mSequence = value;

}

}

#region IExpression 成员

/// <summary>

/// 获取表达式

/// </summary>

/// <param name="driver">数据处理设备提供者</param>

/// <returns>string</returns>

public virtual string GetFilter(HFSoft.Data.IDriverType driver)

{

return " 1=1 " + GetSubString(driver);

}

/// <summary>

/// 获取表达式相关的参数

/// </summary>

/// <param name="driver">数据处理设备提供者</param>

/// <returns>System.Data.IDataParameter[]</returns>

public virtual System.Data.IDataParameter[] GetDataParams(HFSoft.Data.IDriverType driver)

{

return GetSubParams(driver);

}

#endregion

private System.Collections.ArrayList _Expressions = new System.Collections.ArrayList();

private System.Collections.ArrayList _Units = new System.Collections.ArrayList();

/// <summary>

/// 添加相关表达式

/// </summary>

/// <param name="expressions">表达式对象</param>

public void Add(params IExpression[] expressions )

{

Add(UintType.And,expressions);

}

/// <summary>

/// 添加相关表达式

/// </summary>

/// <param name="unittype">表达式合并类型</param>

/// <param name="expressions">表达式对象</param>

public void Add(UintType unittype,params IExpression[] expressions )

{

if(expressions != null)

foreach(IExpression exp in expressions)

{

if(exp != null)

{

_Units.Add(unittype.ToString());

exp.Sequence = this.Sequence +_Expressions.Count;

_Expressions.Add(exp);

}

}

}

/// <summary>

/// 获取内部表达式

/// </summary>

/// <param name="driver">数据设备提供者</param>

/// <returns>string</returns>

protected string GetSubString(HFSoft.Data.IDriverType driver)

{

if(_Units.Count == 0)

return "";

System.Text.StringBuilder sb = new System.Text.StringBuilder();

for(int i =0;i< this._Units.Count;i++)

{

sb.Append(" " +this._Units[i] +" ("+ ((IExpression)_Expressions[i]).GetFilter(driver)+")");

}

return sb.ToString();

}

/// <summary>

/// 获以内部表达式的参数值

/// </summary>

/// <param name="driver">数据设备提供者</param>

/// <returns>System.Data.IDataParameter[]</returns>

protected System.Data.IDataParameter[] GetSubParams(HFSoft.Data.IDriverType driver)

{

if(_Expressions.Count ==0)

return null;

if(_Expressions.Count ==1)

{

return ((IExpression)_Expressions[0]).GetDataParams(driver);

}

System.Collections.ArrayList lst = new System.Collections.ArrayList();

foreach(IExpression exp in this._Expressions)

{

System.Data.IDataParameter[] ps = exp.GetDataParams(driver);

if(ps !=null && ps.Length >0)

{

foreach(System.Data.IDataParameter dp in ps)

{

lst.Add(dp);

}

}

}

Array array = Array.CreateInstance(typeof(System.Data.IDataParameter),lst.Count);

lst.CopyTo(array);

return array as System.Data.IDataParameter[];

}

}

其实Expression只是一个模板类,它自己本生并没有条件处理的能力只是一个简单的1=1;下面我们根据这个模板类派生出具体表达式类型。

/// <summary>

/// 基础表达式抽象类

/// </summary>

[Serializable]

public abstract class BaseExpression:Expression

{

/// <summary>

/// 获取表达式参数对象集

/// </summary>

/// <param name="driver">数据设备提供者</param>

/// <returns>System.Data.IDataParameter[]</returns>

public override System.Data.IDataParameter[] GetDataParams(HFSoft.Data.IDriverType driver)

{

System.Data.IDataParameter p1 = driver.GetParameter(Name+ Sequence,Value);

return ParamsConcat(new System.Data.IDataParameter[]{p1},GetSubParams(driver));

}

/// <summary>

/// 获取表达式

/// </summary>

/// <param name="driver">数据设备提供者</param>

/// <returns>string</returns>

public override string GetFilter(HFSoft.Data.IDriverType driver)

{

System.Text.StringBuilder sb = new System.Text.StringBuilder();

sb.Append(Name);

sb.Append(GetCompareType());

sb.Append(driver.FormatNameForParameter(Name + this.Sequence));

return sb.ToString();

}

/// <summary>

/// 表达式类型

/// =,like等

/// </summary>

/// <returns>string</returns>

protected abstract string GetCompareType();

}

/// <summary>

/// 等于表达式

/// </summary>

[Serializable]

public class EqExpression:BaseExpression

{

/// <summary>

/// 构造等于表达式对象

/// </summary>

public EqExpression()

{

}

/// <summary>

/// 构造指定名称和值的等于表达式对象

/// </summary>

/// <param name="name">名称</param>

/// <param name="value">值</param>

public EqExpression(string name,object value)

{

Name = name;

Value = value;

}

/// <summary>

/// 表达式比较符

/// </summary>

/// <returns>string</returns>

protected override string GetCompareType()

{

return " = ";

}

}

整个条件对象的设计就完成了,文章代码中只有实现了等于的表达式对象;我们可以按自己情况编写更复杂的表达式。条件表达式对象在整个查询对象中是比较核心的部心,因为在整个SQL查询语句中除了这些条件外其它地方都是固定的,剩下的就是把些不同的字符串合并起来,这些东西就不详细说了大家比较了解。

其实Expression只是一个模板类,它自己本生并没有条件处理的能力只是一个简单的1=1;下面我们根据这个模板类派生出具体表达式类型。

/// <summary>

/// 基础表达式抽象类

/// </summary>

[Serializable]

public abstract class BaseExpression:Expression

{

/// <summary>

/// 获取表达式参数对象集

/// </summary>

/// <param name="driver">数据设备提供者</param>

/// <returns>System.Data.IDataParameter[]</returns>

public override System.Data.IDataParameter[] GetDataParams(HFSoft.Data.IDriverType driver)

{

System.Data.IDataParameter p1 = driver.GetParameter(Name+ Sequence,Value);

return ParamsConcat(new System.Data.IDataParameter[]{p1},GetSubParams(driver));

}

/// <summary>

/// 获取表达式

/// </summary>

/// <param name="driver">数据设备提供者</param>

/// <returns>string</returns>

public override string GetFilter(HFSoft.Data.IDriverType driver)

{

System.Text.StringBuilder sb = new System.Text.StringBuilder();

sb.Append(Name);

sb.Append(GetCompareType());

sb.Append(driver.FormatNameForParameter(Name + this.Sequence));

return sb.ToString();

}

/// <summary>

/// 表达式类型

/// =,like等

/// </summary>

/// <returns>string</returns>

protected abstract string GetCompareType();

}

/// <summary>

/// 等于表达式

/// </summary>

[Serializable]

public class EqExpression:BaseExpression

{

/// <summary>

/// 构造等于表达式对象

/// </summary>

public EqExpression()

{

}

/// <summary>

/// 构造指定名称和值的等于表达式对象

/// </summary>

/// <param name="name">名称</param>

/// <param name="value">值</param>

public EqExpression(string name,object value)

{

Name = name;

Value = value;

}

/// <summary>

/// 表达式比较符

/// </summary>

/// <returns>string</returns>

protected override string GetCompareType()

{

return " = ";

}

}

整个条件对象的设计就完成了,文章代码中只有实现了等于的表达式对象;我们可以按自己情况编写更复杂的表达式。条件表达式对象在整个查询对象中是比较核心的部心,因为在整个SQL查询语句中除了这些条件外其它地方都是固定的,剩下的就是把些不同的字符串合并起来,这些东西就不详细说了大家比较了解。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有