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

对象|语句

 
在开发数据库应用的过程难免会编写大量的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查询语句中除了这些条件外其它地方都是固定的,剩下的就是把些不同的字符串合并起来,这些东西就不详细说了大家比较了解。

时间: 2024-10-29 00:52:07

SQL查询语句对象化的实现(C#)的相关文章

SQL查询语句中的bool类型字段值的写法

  SQL查询语句中的bool类型字段值的写法 没有系统地看过SQL语句的写法说明,只是看了一些常用SQL语句的例子.今天写了条select * from table where sex='true',老是提示标准数据类型不匹配(我用的Access),检查了半天,原来sex字段作为bool(是/否)类型,在SQL语句中其值不需要用''引起来.

15个初学者必看的基础SQL查询语句

本文将分享15个初学者必看的基础SQL查询语句,都很基础,但是你不一定都会,所以好好看看吧. 1.创建表和数据插入SQL 我们在开始创建数据表和向表中插入演示数据之前,我想给大家解释一下实时数据表的设计理念,这样也许能帮助大家能更好的理解SQL查询. 在数据库设计中,有一条非常重要的规则就是要正确建立主键和外键的关系. 现在我们来创建几个餐厅订单管理的数据表,一共用到3张数据表,Item Master表.Order Master表和Order Detail表. 创建表: 创建Item Maste

sql-数据库 SQL查询语句 简化语句

问题描述 数据库 SQL查询语句 简化语句 请问 怎样从上面的数据表中查询出下面表的效果?求大神指教 解决方案 group by month 解决方案二: select months 月份type1+type2+type3 总数case when type1>0 then 1 else 0 then 执照1case when type2>0 then 1 else 0 then 执照2case when type3>0 then 1 else 0 then 执照3from(select

hibernate-web后台的sql查询语句问题

问题描述 web后台的sql查询语句问题 我使用spring+hibernate的框架做的后台,在dao层中sql查询语句查询所有select * from tbplayer t1 where nickname='"+shopID+"'就可以查出结果,然后在拼接显示自己想要的内容,但是一旦换成查某个字段select p3_account from tb_player t1 where nickname='"+shopID+"'就报错,说没有psn这列,但是我的语句中

图片-qiushou求SQL查询语句问题, SQL语句忘记怎么写了

问题描述 qiushou求SQL查询语句问题, SQL语句忘记怎么写了 第一列是-主键-地区-销售人员-销售总额, 请问查询-每个地区销售金额最少的人是谁 解决方案 select * from ( select rank() over(partition by region order by total) as rid ,orderid,region,sales,total from salesorder ) t where t.rid = 1 解决方案二: select * from sale

[数据库] SQL查询语句表行列转换及一行数据转换成两列

本文主要讲述了SQL查询语句表之间的行列转换,同时也包括如何将一行数据转换成两列数据的方法.子查询的应用.decode函数的用法.希望文章对你有所帮助~ 1.创建数据库表及插入数据 2.子查询统计不同性质的学生总数 3.一行数据转换成两列数据 union all 4.表行列数据转换(表转置) 1.创建数据库表及插入数据 创建数据库.创建学生表并设置主键.插入数据代码如下: --创建数据库 create database StudentMS --使用数据库 use StudentMS --创建学生

sql-数据库新手提问:SQL查询语句

问题描述 数据库新手提问:SQL查询语句 有3张表:学生表(学号,姓名,性别,年龄);课程表(课程号,课程名,学期):成绩表(学号,课程号,分数). 现在根据学号和学期查询某个同学的成绩信息:例如学号为001,学期是1的. 解决方案 select 学生表.姓名 课程表.课程 成绩表.分数 from 学生表,课程表, 成绩表 where 学生表.学号 = 成绩表.学号 and 课程表.课程号 = 成绩表.课程号 and 学生表.学号 = 001 and 课程表.学期 =1

mysql 查询指定日期时间内容sql查询语句

mysql教程 查询指定日期时间内容sql查询语句 在数据库教程设计时必须注意时间字段最好为int(4)这样,保存在数据库的时一个数字型日期时间截,我们可以用mktime函数求出当前日期的时间截进行加减就OK了,下面看实例 $time = time();   //一个月 $lastMonth = mktime(date('h'),date('i'),date('s'),date('m')-1,date('d'),date('y')); $where .= "  dtime < $lastM

sql 股票 复杂查询-股票数据复杂sql查询语句

问题描述 股票数据复杂sql查询语句 数据库表如下 CREATE TABLE STOCKITEM( STOCKDATE DATE NOT NULL, STOCKCODE CHAR(50) NOT NULL, STOCKNAME CHAR(50) NOT NULL, OPENPRICE DOUBLE NOT NULL, CLOSEPRICE DOUBLE NOT NULL, HIGHESTPRICE DOUBLE NOT NULL, LOWESTPRICE DOUBLE NOT NULL, FLU