AppFramework1.0数据库访问组件使用说明(六)QueryFilter的使用

 
1.1  QueryFilter的使用
QueryFilter是AppFramework提供的一个功能强大、不需要编写SQL语句、跨数据库、参数化、执行性能优异的查询条件构造器。有了QueryFilter我们不需要再拼装SQL语句,不用再担心单引号导致SQL注入的安全漏洞,不用担心被众多的AND、OR、NOT等逻辑运算符弄得晕头转向,不用区分处理TO_DATE、UPPER等无法跨数据库的表达式。因此,QueryFilter是AppFramework提供的一项非常重要的特色功能,极大地提升了数据库应用系统的开发效率。
1.1.1  QueryFilter的结构
QueryFilter 它是一种由多个项组成可嵌套的多层树状结构,通一层上的项与项之间是“与”或者“或”的逻辑关系,最顶层的项集合可以通过Items 属性获取到。QueryFilter 的结构非常直观简单,例如,页面上有三个查询条件,如下所示:
 
 
这三个条件就对应到三个QueryFilter 项,查询项之间的关系为“与”,代表着只有三个条件同时满足才能命中记录。QueryFilter 项可以由下列几种不同的类型组成:
1、       string :SQL 表达式,确保可以实现任意功能,但无法保证可移植性;
2、       DBField :字段表达式,具有较好的可移植性,可以描述“字段 操作符 值(或表达式)”这种形式的表达式,其中“值(或表达式)”可以有三种形式,分别是SQL 表达式、常量、SelectStatement 子查询;
3、       QueryFilter :嵌套的QueryFilter ,例如:A and (B or C) ,其中的(B or C) 可以作为一个嵌套的QueryFilter
4、       SqlMap :用于集成SQL 模板(SqlTemplate )提供的功能。SQL 模板具有较强的可视性,容易编写和维护,在配置文件里编写后由代码生成器直接生成SqlMap 的子类,然后可以作为QueryFilter 的一个项来运行,这种做法可以提高SqlTemplate 的复用度,也提高了QueryFilter 的灵活性;
 
QueryFilter 属性方法说明:
属性/ 方法
类型
说明
Items
ArrayList
用来存放组合条件的集合,其元素可以是 DBField 、QueryFilter 、String 、SqlMap
And
bool
指定各个组合条件之间的关系, 默认 And
Not
bool
指定是否对当前QueryFilter 进行取反运算,默认 false
QueryFilter(bool isAnd)
构造。
isAnd 为true 表示各个组合条件之间关系为And; 为false: 表示为Or ;默认为 true
Add(DBField field)
void
添加一个参数条件, 注意,field 的构造函数可以构造为子查询,因此此方法可以增加一项子查询
Add(QueryFilter filter)
void
添加一个子组合条件
AddSubFilter(bool isAnd)
QueryFilter
添加一个子组合条件
Add(string expression)
void
添加一个表达式
Add(string fieldName, DBOperator op, string queryString)
void
添加字段查询条件,若 queryString 为 null 或空则忽略
AddString(string fieldName, string queryString)
void
添加字符字段查询条件,不区分大小写,全模糊。若 queryString 为 null 或空则忽略。
AddString(string fieldName, string queryString, QueryFuzzyType fuzzyType)
void
添加字符字段查询条件,不区分大小写。若 queryString 为 null 或空则忽略。
AddString(string fieldName, string queryString, QueryFuzzyType fuzzyType, bool caseSensitive)
void
添加字符字段查询条件。若 queryString 为 null 或空则忽略
AddString(string fieldName, string queryString, QueryFuzzyType fuzzyType, bool caseSensitive)
void
添加字符字段查询条件。若 queryString 为 null 或空则忽略
AddDateRangeBegin(string fieldName, object date)
void
添加日期范围的开始日期。若 date 为 null 或空串则忽略
AddDateRangeEnd(string fieldName, object date)
void
添加日期范围的结束日期。若 date 为 null 或空串则忽略
Add(SqlMap sqlMap)
void
添加 SqlMap
 
1.1.2  用QueryFilter实现查询
在上一章节提到的例子中,可以这样构造QueryFilter:
QueryFilter filter = new QueryFilter(true); // true 表示项之间的逻辑关系为“ and
 
// 添加“名称”查询条件 NAME like "%xxx%"
filter.Items.Add(new DBField("NAME", DBOperator.Like, "'%" + txtName.Text + "%'");
 
// 添加“开始日期”查询条件 START_DATE >= xxx
filter.Add(new DBField("START_DATE", DBOperator.GreatThanOrEqual, DateTime.Parse(txtStartTime.Text).Date));
 
// 添加“结束日期”查询条件 END_DATE <= xxx
filter.Add(new DBField("END_DATE", DBOperator.LessThan, DateTime.Parse(txtEndTime.Text).Date.AddDays(1)));
 
using (IDBSession session = DBSessionManager.Default.GetSession())
{
    DataTable dt = session. QueryDataTable("BAS_USER", "*", filter, null);
}
 
注意,添加“名称”查询条件也可以用直接添加SQL 表达式的方式,但要对输入项txtName.Text 进行单引号转义以避免产生SQL 注入漏洞,上面基于DBField 构造查询条件因生成参数化SQL 则没有漏洞问题。
// 添加“名称”查询条件,直接添加 SQL 表达式
filter.Add("name like '%"+txtName.Text.Replace("'", "''")+"%'");
但上面的写法还是过于简单,实际上对于字符串查询条件一般都要过滤掉头尾的空格,并且还要检验用户是否输入了,输入了才产生查询SQL ,因此完整的写法应该是:
QueryFilter filter = new QueryFilter(true); // true 表示项之间的逻辑关系为“ and
// 添加“名称”查询条件 NAME like "%xxx%"
string name = txtName.Text.Trim();
if (name.Length > 0)
{
    filter.Items.Add(new DBField("NAME", DBOperator.Like, "'%" + name + "%'");
}
 
// 添加“开始日期”查询条件 START_DATE >= xxx
if (txtStartTime.Text.Length > 0)
{
    filter.Add(new DBField("START_DATE", DBOperator.GreatThanOrEqual, DateTime.Parse(txtStartTime.Text).Date));
}
 
// 添加“结束日期”查询条件 END_DATE <= xxx
if (txtEndTime.Text.Length > 0)
{
    filter.Add(new DBField("END_DATE", DBOperator.LessThan, DateTime.Parse(txtEndTime.Text).Date.AddDays(1)));
}
 
using (IDBSession session = DBSessionManager.Default.GetSession())
{
    DataTable dt = session. QueryDataTable("BAS_USER", "*", filter, null);
}
为了简化查询业务的实现,QueryFilter 提供了几个非常智能的方法,能够快速实现输入预处理、非空判断、查询条件构造等,推荐使用下列方法实现查询业务:
QueryFilter filter = new QueryFilter(true); // true 表示项之间的逻辑关系为“ and
 
// 添加“名称”查询条件 NAME like "%xxx%"
filter.Items.AddString("NAME", txtName.Text);
 
// 添加“开始日期”查询条件 START_DATE >= xxx
filter.AddDateRangeBegin("START_DATE", txtStartTime.Text);
 
// 添加“结束日期”查询条件 END_DATE <= xxx
filter. AddDateRangeEnd("END_DATE", txtEndTime.Text);
 
using (IDBSession session = DBSessionManager.Default.GetSession())
{
    DataTable dt = session. QueryDataTable("BAS_USER", "*", filter, null);
}
注意,上述代码中许多常量被硬编码了,例如字段名“NAME ”、“BEGIN_DATE ”、表名“BAS_USER ”等,一种好的做法是采用代码生成器生成的元数据常量来编码,例如:
 
filter.AddString(BasUserDef.Name_FieldName, txtUserName.Text, QueryFuzzyType.RightFuzzy);
filter.AddDateRangeBegin(BasUserDef.UpdatedTime_FieldName, beginDate.Text);
filter.AddDateRangeEnd(BasUserDef.UpdatedTime_FieldName, endDate.Text);
 
此外,AddString 有多个重载方法,支持多种模糊查询选项,包括大小写是否区分,开发者可以根据实际需要选用其中一个方法:
///
/// 添加字符字段查询条件,不区分大小写,全模糊。若 queryString null 或空则忽略。
///
/// 字段名
/// 查询值
public void AddString(string fieldName, string queryString);
 
///
/// 添加字符字段查询条件,不区分大小写。若 queryString null 或空则忽略。
///
/// 字段名
/// 查询值
/// 模糊方式
public void AddString(string fieldName, string queryString, QueryFuzzyType fuzzyType);
 
///
/// 添加字符字段查询条件。若 queryString null 或空则忽略。
///
/// 字段名
/// 查询值
/// 模糊方式
/// 是否区分大小写
public void AddString(string fieldName, string queryString, QueryFuzzyType fuzzyType, bool caseSensitive);
 
 

你可能感兴趣的:(AppFramework1.0数据库访问组件使用说明(六)QueryFilter的使用)