您的位置:首页 > 移动开发 > Objective-C

企业应用架构模式——QueryObject模式

2012-12-29 13:29 302 查看
场景

比如我们有个Employee实体,属性有EmployeeID(雇员id)、NationalIDNumber(雇员标志号,如身份证)、ManagerID(雇员上司id)、Title(职位)、MaritalStatus(婚姻状态)、Gender(性别)、HireDate(雇佣日期)、SalariedFlag(工作性质,计时或月薪)。我们写数据库层时经常会遇到这样的需求:

查询标志号为"001”的雇员

publicclassEmployeeRepository:IRepository<Employee>
{
publicEmployeeFind(objectid)
{}
}


查询计时或月薪的雇员

publicclassEmployeeRepository:IRepository<Employee>
{
publicIEnumerable<Employee>FindSalariedEmployee(SalariedFlagsalariedFlag)
{}
}

可以看出只要我们有通过对象属性来查询对象,就要在相应的数据层增加对应的Findxxx方法,不过这只是单一的查询,如果存在组合条件的查询,Employee仓储中会充斥大量的检索方法。

QueryObject模式

QueryObject(查询对象)是一个解释器,也就是说,他是由多个对象组成的结构,该结构可以自身转化为一个sql查询。可以通过引用类的和属性来创建对应数据库表和列的查询。

查询对象的好处

1、完全将底层数据库的查询语言抽象出来,因此将数据库持久化和检索的基础设施关注点从业务层中分离出来。

2、对于多个数据库,通过设计查询对象,根据运行的数据库来产生不同的sql,屏蔽了各种不同sql语法中的差别。

3、消除对数据库的查询冗余,如果在先前的会话中运行过相同的查询,可以使用查询对象从标志映射中选取对象。

QueryObject模型类图





实现QueryObject模式

首先创建一个枚举CriteriaOperator用来处理查询条件的映射

publicenumCriteriaOperator

[code]{
Equal,//=

LessThanOrEqual,//<=

NotApplicable,//≠

LessThan,//<

GreaterThan,//>

GreaterThanOrEqual,//>=

Like//%

}

[/code]

创建查询过滤器的类Criterion

///<summary>

[code]///查询过滤器
///</summary>

publicclassCriterion

{

privatestring_propertyName;//实体属性

privateobject_value;//进行比较的值

privateCriteriaOperator_criteriaOperator;//比较操作符


publicCriterion(stringpropertyName,objectvalue,CriteriaOperatorcriteriaOperator)

{

_propertyName=propertyName;

_value=value;

_criteriaOperator=criteriaOperator;

}


publicstringPropertyName

{

get{return_propertyName;}

}


publicobjectValue

{

get{return_value;}

}

publicCriteriaOperatorCriteriaOperator

{

get{return_criteriaOperator;}

}


}

[/code]

创建一个用于表示排序属性的类OrderByClause


publicclassOrderByClause

[code]{
publicstringPropertyName{get;set;}//属性名对应数据库表的列名


publicboolDesc{get;set;}//descorasc

}

[/code]

创建另一个枚举QueryOperator,用来表示条件的连字符and或者or


publicenumQueryOperator

[code]{
And,

Or

}

[/code]
有时候复杂的查询对象难以构建,我们会通过存储过程或视图来处理此种情况,需要构建一个枚举QueryName用来指示是存储过程(视图)还是构建动态的sql语句


publicenumQueryName

[code]{
Dynamic=0,//动态创建

RetrieveOrdersUsingAComplexQuery=1//使用已经创建好了的存储过程、视图、特别是查询比较复杂时使用存储过程

}

[/code]
最后创建Query类,用来组合查询条件(Criterion)、查询条件连字符(QueryOperator),排序(OrderByClause)


publicclassQuery

[code]{
privateQueryName_name;


privateIList<Criterion>_criteria;//查询条件


publicQuery():this(QueryName.Dynamic,newList<Criterion>())

{}

publicQuery(QueryNamename,IList<Criterion>criteria)

{

_name=name;

_criteria=criteria;

}


publicQueryNameName

{

get{return_name;}

}


///<summary>

///判断是存储过程还是动态sql

///</summary>

///<returns></returns>

publicboolIsNamedQuery()

{

returnName!=QueryName.Dynamic;

}


publicIEnumerable<Criterion>Criteria

{

get{return_criteria;}

}


publicvoidAdd(Criterioncriterion)

{

if(!IsNamedQuery())

{

_criteria.Add(criterion);

}

else

{

thrownewApplicationException("Youcannotaddadditionalcriteriatonamedqueries");

}

}

//查询条件连字符

publicQueryOperatorQueryOperator

{

get;

set;

}

//排序列

publicOrderByClauseOrderByProperty

{

get;

set;

}


}

[/code]

使用QueryObject模式

仓储层(Repository)接口


publicinterfaceIRepository<T>

[code]{
intAdd(Tentity);

intSave(Tentity);

voidDelete(Tentity);

TFind(objectid);

TFind(Queryquery);

IEnumerable<T>FindBy(Queryquery);

IEnumerable<T>FindBy(Queryquery,intpageSize,intpageCount);

}

[/code]
创建一个翻译器,将查询对象翻译成sql语句


publicstaticclassAdmissionTicketOrderQueryTranslator

[code]{
privatestaticreadonlystringbaseSelectQuery="SELECT*FROMAdmissionTicketOrder";


publicstaticvoidTranslateInfo(thisQueryquery,SqlCommandcmd)

{

if(query.IsNamedQuery())

{

cmd.CommandType=CommandType.StoredProcedure;

cmd.CommandText=query.Name.ToString();

foreach(Criterioncriteriainquery.Criteria)

{

cmd.Parameters.Add(newSqlParameter("@"+criteria.PropertyName,criteria.Value));

}

}

else

{

StringBuildersqlQuery=newStringBuilder();

sqlQuery.Append(baseSelectQuery);

bool_isNotfirstFilterClause=false;


if(query.Criteria.Count()>0)

{

sqlQuery.Append("WHERE");

}


foreach(Criterioncriterioninquery.Criteria)

{

if(_isNotfirstFilterClause)

{

sqlQuery.Append(GetQueryOperator(query));

}

sqlQuery.Append(AddFilterClauseFrom(criterion));

cmd.Parameters.Add(newSqlParameter("@"+criterion.PropertyName,criterion.Value));

_isNotfirstFilterClause=true;

}

sqlQuery.Append(GenerateOrderByClauseFrom(query.OrderByProperty));

cmd.CommandType=CommandType.Text;

cmd.CommandText=sqlQuery.ToString();

}

}


privatestaticstringGenerateOrderByClauseFrom(OrderByClauseorderByClause)

{

returnString.Format("ORDERBY{0}{1}",

FindTableColumnFor(orderByClause.PropertyName),orderByClause.Desc?"DESC":"ASC");

}


///<summary>

///

///</summary>

///<paramname="query"></param>

///<returns></returns>

privatestaticstringGetQueryOperator(Queryquery)

{

if(query.QueryOperator==QueryOperator.And)

{

return"AND";

}

else

{

return"OR";

}

}


privatestaticstringAddFilterClauseFrom(Criterioncriterion)

{

returnstring.Format("{0}{1}@{2}",FindTableColumnFor(criterion.PropertyName),FindSQLOperatorFor(criterion.CriteriaOperator),criterion.PropertyName);

}


privatestaticstringFindSQLOperatorFor(CriteriaOperatorcriteriaOperator)

{

switch(criteriaOperator)

{

caseCriteriaOperator.Equal:

return"=";

caseCriteriaOperator.LessThanOrEqual:

return"<=";

caseCriteriaOperator.NotApplicable:

return"<>";

caseCriteriaOperator.LessThan:

return"<";

caseCriteriaOperator.GreaterThan:

return">";

caseCriteriaOperator.GreaterThanOrEqual:

return">=";

default:

thrownewApplicationException("Nooperatordefined.");

}

}


privatestaticstringFindTableColumnFor(stringpropertyName)

{

switch(propertyName)

{

case"ID":

return"ID";

case"OrderID":

return"OrderID";

case"TicketId":

return"TicketId";

case"OrderUserName":

return"OrderUserName";

case"OrderUserSex":

return"OrderUserSex";

case"OrderUserPhone":

return"OrderUserPhone";

case"ProviderContactName":

return"ProviderContactName";

case"TicetUseDateTime":

return"TicetUseDateTime";

case"SalePrice":

return"SalePrice";

case"BuyPrice":

return"BuyPrice";

case"BuyAmount":

return"BuyAmount";

case"TicketType":

return"TicketType";

default:

thrownewApplicationException("Nocolumndefinedforthisproperty.");

}

}


}


[/code]

仓储实现层


publicclassAdmissionTicketOrderRepository:IRepository<AdmissionTicketOrder>

[code]{
privateSqlHelper_sqlHelper;


publicAdmissionTicketOrderRepository(SqlHelpersqlHelper)

{

_sqlHelper=sqlHelper;

}


privatestaticreadonlystringinsertOrderExtendSql="sp_InsertOrUpdateAdmissionTicketOrder";

publicintAdd(AdmissionTicketOrderentity)

{

using(varcmd=_sqlHelper.PrepareStoredSqlCommand(insertOrderExtendSql))

{

cmd.AddParam("@ID",entity.ID);

cmd.AddParam("@OrderID",entity.OrderID);

cmd.AddParam("@TicketId",entity.TicketId);

cmd.AddParam("@OrderUserName",entity.OrderUserName);

cmd.AddParam("@OrderUserSex",entity.OrderUserSex);

cmd.AddParam("@OrderUserPhone",entity.OrderUserPhone);

cmd.AddParam("@ProviderContactName",entity.ProviderContactName);

cmd.AddParam("@ProviderContactPhone",entity.ProviderContactPhone);

cmd.AddParam("@TicetUseDateTime",entity.TicetUseDateTime);

cmd.AddParam("@IsNeed",entity.IsNeed);

cmd.AddParam("@BillAddress",entity.BillAddress);

cmd.AddParam("@BuyPrice",entity.BuyPrice);

cmd.AddParam("@SalePrice",entity.SalePrice);

cmd.AddParam("@BuyAmount",entity.BuyAmount);

cmd.AddParam("@GetTicketAddress",entity.GetTicketAddress);

cmd.AddParam("@TicketType",entity.TicketType);

varparm=cmd.AddReturnValueParameter("ReturnValue");

cmd.ExecuteNonQuery();

return(int)parm.Value;

}

}


publicintSave(AdmissionTicketOrderentity)

{

returnAdd(entity);

}


privatestaticreadonlystringdeleteOrder="DELETEAdmissionTicketOrderWHEREID=@Id";

publicvoidDelete(AdmissionTicketOrderentity)

{

using(varcmd=_sqlHelper.PrepareTextSqlCommand(deleteOrder))

{

cmd.AddParam("@Id",entity.ID);

cmd.ExecuteNonQuery();

}

}


privatestaticreadonlystringselectOrder="SELECT*FROMAdmissionTicketOrderWHEREID=@Id";

publicAdmissionTicketOrderFind(objectid)

{

using(varcmd=_sqlHelper.PrepareTextSqlCommand(selectOrder))

{

cmd.AddParam("@Id",id);

using(varreader=cmd.ExecuteReader())

{

if(reader.Read())

{

return(newAdmissionTicketOrder

{

Id=reader.GetValue<int>("Id"),

OrderID=reader.GetValue<int>("OrderID"),

TicketId=reader.GetValue<int>("TicketId"),

OrderUserName=reader.GetValue<string>("OrderUserName"),

OrderUserSex=reader.GetValue<int>("OrderUserSex"),

OrderUserPhone=reader.GetValue<string>("OrderUserPhone"),

ProviderContactName=reader.GetValue<string>("ProviderContactName"),

ProviderContactPhone=reader.GetValue<string>("ProviderContactPhone"),

TicetUseDateTime=reader.GetValue<DateTime>("TicetUseDateTime"),

IsNeed=reader.GetValue<bool>("IsNeed"),

BillAddress=reader.GetValue<string>("BillAddress"),

SalePrice=reader.GetValue<decimal>("SalePrice"),

BuyPrice=reader.GetValue<decimal>("BuyPrice"),

BuyAmount=reader.GetValue<decimal>("BuyAmount"),

GetTicketAddress=reader.GetValue<string>("GetTicketAddress"),

TicketType=reader.GetValue<string>("TicketType")

});

}

returnnull;

}

}

}


publicAdmissionTicketOrderFind(Queryquery)

{

SqlCommandcmd=_sqlHelper.PrepareSqlCommand();

query.TranslateInfo(cmd);

using(varreader=cmd.ExecuteReader())

{

if(reader.Read())

{

return(newAdmissionTicketOrder

{

Id=reader.GetValue<int>("Id"),

OrderID=reader.GetValue<int>("OrderID"),

TicketId=reader.GetValue<int>("TicketId"),

OrderUserName=reader.GetValue<string>("OrderUserName"),

OrderUserSex=reader.GetValue<int>("OrderUserSex"),

OrderUserPhone=reader.GetValue<string>("OrderUserPhone"),

ProviderContactName=reader.GetValue<string>("ProviderContactName"),

ProviderContactPhone=reader.GetValue<string>("ProviderContactPhone"),

TicetUseDateTime=reader.GetValue<DateTime>("TicetUseDateTime"),

IsNeed=reader.GetValue<bool>("IsNeed"),

BillAddress=reader.GetValue<string>("BillAddress"),

SalePrice=reader.GetValue<decimal>("SalePrice"),

BuyPrice=reader.GetValue<decimal>("BuyPrice"),

BuyAmount=reader.GetValue<decimal>("BuyAmount"),

GetTicketAddress=reader.GetValue<string>("GetTicketAddress"),

TicketType=reader.GetValue<string>("TicketType")

});

}

returnnull;

}

}


publicIEnumerable<AdmissionTicketOrder>FindBy(Queryquery)

{

IList<AdmissionTicketOrder>admissionTicketOrders=newList<AdmissionTicketOrder>();

SqlCommandcmd=_sqlHelper.PrepareSqlCommand();

query.TranslateInfo(cmd);

using(SqlDataReaderreader=cmd.ExecuteReader())

{

while(reader.Read())

{

admissionTicketOrders.Add(

newAdmissionTicketOrder

{

Id=reader.GetValue<int>("Id"),

OrderID=reader.GetValue<int>("OrderID"),

TicketId=reader.GetValue<int>("TicketId"),

OrderUserName=reader.GetValue<string>("OrderUserName"),

OrderUserSex=reader.GetValue<int>("OrderUserSex"),

OrderUserPhone=reader.GetValue<string>("OrderUserPhone"),

ProviderContactName=reader.GetValue<string>("ProviderContactName"),

ProviderContactPhone=reader.GetValue<string>("ProviderContactPhone"),

TicetUseDateTime=reader.GetValue<DateTime>("TicetUseDateTime"),

IsNeed=reader.GetValue<bool>("IsNeed"),

BillAddress=reader.GetValue<string>("BillAddress"),

SalePrice=reader.GetValue<decimal>("SalePrice"),

BuyPrice=reader.GetValue<decimal>("BuyPrice"),

BuyAmount=reader.GetValue<decimal>("BuyAmount"),

GetTicketAddress=reader.GetValue<string>("GetTicketAddress"),

TicketType=reader.GetValue<string>("TicketType")

}

);

}

}

returnadmissionTicketOrders;

}


publicIEnumerable<AdmissionTicketOrder>FindBy(Queryquery,intpageSize,intpageCount)

{

returnFindBy(query).Skip(pageSize*pageCount).Take(pageCount);

}

}

[/code]

控制台调用


staticvoidMain(string[]args)

[code]{
using(varsqlHelper=newSqlHelper("ConnectionString"))

{

AdmissionTicketOrderRepositoryator=newAdmissionTicketOrderRepository(sqlHelper);

AdmissionTicketOrderato=ator.Find(2);


Queryquery=newQuery();


query.Add(newCriterion("SalePrice",100,CriteriaOperator.GreaterThan));

query.QueryOperator=QueryOperator.And;

query.Add(newCriterion("TicketType","单一票型",CriteriaOperator.Equal));

query.Add(newCriterion("BuyAmount",250,CriteriaOperator.LessThan));

query.QueryOperator=QueryOperator.And;

query.OrderByProperty=newOrderByClause{PropertyName="TicetUseDateTime",Desc=true};


List<AdmissionTicketOrder>list=ator.FindBy(query).ToList();

foreach(variteminlist)

{

Console.WriteLine("{0}{1}{2}{3}",item.ID,item.ProviderContactName,item.BuyPrice,item.SalePrice);

}

}

Console.Read();


}

[/code]
源代码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: