使用OQL+SQLMAP解决ORM多表复杂的查询问题
2011-02-25 19:08
281 查看
一般情况下,使用ORM框架来完成单个实体的查询是很方便的,但如果有复杂的查询条件,普通的ORM组件比较困难,PDF.NET数据开发框架的ORM实体类查询语言--OQL,使得构造复杂的查询条件成为可能,参加我的其它相关文章。
很多ORM框架都只能处理单个实体的查询,但如果要连表查询就比较困难了,主要问题是连表查询的结果无法投射到一个实体类中,这时候只有动态创建一个类来处理,比如LINQ的Select功能。在PDF.NET数据开发框架中,多表连接查询推荐使用SQL-MAP功能(参加我的相关文章),将复杂的SQL语句写到SQL-MAP配置文件中,然后使用代码生成器生成SqlMapDal类文件,供业务层使用。
今天有一个同事需要在实体类的条件中增加一个复杂的In查询,由于In的条件有4万条,采用SQL的In查询效率极其低下,但是采用Inner Join查询能够提升5倍的查询效率,而框架的ORM又不支持多表连接查询,单独使用SQL-MAP功能,要大量修改原有代码,原有代码是一个长达4000行的方法,那个方法最有大量的循环和分支,用于构造实体类的查询条件对象(OQLCompare对象),最终构造了一个复杂的OQL查询条件:
OQL oql=GetOQLbyBussiness();//这个方法有4000行代码;
string sql=oql.ToString();//大致是 select * from table1 where condition1
sql=GetInnerJoinSql(sql,"另外一个表的查询语句");
//执行这个方法将得到大致的查询语句
//select * from table1 t1 inner join table2 t2 where t1.CID=t2.Cid and condition1
本来使用 EntityQuery<EntityModelClass>.Query(oql) 即可获得 List<EntityModelClass>,但现在为了添加另外一个表的查询,将oql转换成了sql语句,怎么能够再次生成实体类呢?
现在,我们可以使用SQL-MAP来帮助了。
打开原来的SqlMapDal文件,为了不让代码生成器覆盖自动生成的文件,我们新建一个分部文件,手写如下代码:
using System;
using System.Data;
using System.Collections.Generic;
using PWMIS.DataMap.SqlMap;
using PWMIS.DataMap.Entity;
using PWMIS.Common;
using XXModel;
namespace XXDAL.SqlMapDAL
{
public partial class CustomerManage
: DBMapper
{
public List<CustomerClassification> GetCustomerList(string sql, Dictionary<string, object> ps)
{
IDataParameter[] paras = new IDataParameter[ps.Count];
int i = 0;
foreach (string key in ps.Keys)
paras[i++] = CurrentDataBase.GetParameter(key, ps[key]);
return EntityQuery<CustomerClassification>.QueryList(CurrentDataBase.ExecuteReader(CurrentDataBase.ConnectionString, System.Data.CommandType.Text, sql, paras));
}
}
}
然后,在业务层中,如下调用即可:
XXDAL.SqlMapDAL.CustomerManage manage=new XXDAL.SqlMapDAL.CustomerManage();
List<CustomerClassification> customerClass=manage.GetCustomerList(sql,oql.DataParameters);
这样就获得了我们的最终结果。
请注意,我们把oql的参数对象DataParameters 传递给了DAL方法,用于构造参数化查询。
总结:
结合使用PDF.NET框架的OQL+SQLMAP,可以在不放弃实体类的便利情况下,进行复杂的多表查询!
很多ORM框架都只能处理单个实体的查询,但如果要连表查询就比较困难了,主要问题是连表查询的结果无法投射到一个实体类中,这时候只有动态创建一个类来处理,比如LINQ的Select功能。在PDF.NET数据开发框架中,多表连接查询推荐使用SQL-MAP功能(参加我的相关文章),将复杂的SQL语句写到SQL-MAP配置文件中,然后使用代码生成器生成SqlMapDal类文件,供业务层使用。
今天有一个同事需要在实体类的条件中增加一个复杂的In查询,由于In的条件有4万条,采用SQL的In查询效率极其低下,但是采用Inner Join查询能够提升5倍的查询效率,而框架的ORM又不支持多表连接查询,单独使用SQL-MAP功能,要大量修改原有代码,原有代码是一个长达4000行的方法,那个方法最有大量的循环和分支,用于构造实体类的查询条件对象(OQLCompare对象),最终构造了一个复杂的OQL查询条件:
OQL oql=GetOQLbyBussiness();//这个方法有4000行代码;
string sql=oql.ToString();//大致是 select * from table1 where condition1
sql=GetInnerJoinSql(sql,"另外一个表的查询语句");
//执行这个方法将得到大致的查询语句
//select * from table1 t1 inner join table2 t2 where t1.CID=t2.Cid and condition1
本来使用 EntityQuery<EntityModelClass>.Query(oql) 即可获得 List<EntityModelClass>,但现在为了添加另外一个表的查询,将oql转换成了sql语句,怎么能够再次生成实体类呢?
现在,我们可以使用SQL-MAP来帮助了。
打开原来的SqlMapDal文件,为了不让代码生成器覆盖自动生成的文件,我们新建一个分部文件,手写如下代码:
using System;
using System.Data;
using System.Collections.Generic;
using PWMIS.DataMap.SqlMap;
using PWMIS.DataMap.Entity;
using PWMIS.Common;
using XXModel;
namespace XXDAL.SqlMapDAL
{
public partial class CustomerManage
: DBMapper
{
public List<CustomerClassification> GetCustomerList(string sql, Dictionary<string, object> ps)
{
IDataParameter[] paras = new IDataParameter[ps.Count];
int i = 0;
foreach (string key in ps.Keys)
paras[i++] = CurrentDataBase.GetParameter(key, ps[key]);
return EntityQuery<CustomerClassification>.QueryList(CurrentDataBase.ExecuteReader(CurrentDataBase.ConnectionString, System.Data.CommandType.Text, sql, paras));
}
}
}
然后,在业务层中,如下调用即可:
XXDAL.SqlMapDAL.CustomerManage manage=new XXDAL.SqlMapDAL.CustomerManage();
List<CustomerClassification> customerClass=manage.GetCustomerList(sql,oql.DataParameters);
这样就获得了我们的最终结果。
请注意,我们把oql的参数对象DataParameters 传递给了DAL方法,用于构造参数化查询。
总结:
结合使用PDF.NET框架的OQL+SQLMAP,可以在不放弃实体类的便利情况下,进行复杂的多表查询!
相关文章推荐
- 在sqlserver中如何使用CTE解决复杂查询问题
- 使用CTE解决复杂查询的问题
- 在sqlserver中如何使用CTE解决复杂查询问题
- SQL反模式学习笔记18 减少SQL查询数据,避免使用一条SQL语句解决复杂问题
- 解决Access数据库中"操作必须使用一个可更新的查询"问题
- 解决使用sap数据库驱动查询hana数据库时,like '%param%' 失效问题
- 如何解决PHP使用mysql_query查询超大结果集超内存问题
- 解决绕过android下apk使用usb设备权限查询相应问题,自动获取usb权限
- mybatis使用foreach批次插入,解决sequence只查询一次的问题(在此,我只看union all 部分)
- 使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的解决
- 解决绕过android下apk使用usb设备权限查询相应问题,自动获取usb权限
- 解决绕过android下apk使用usb设备权限查询相应问题,自动获取usb权限
- 使用OQL“语言”构造ORM实体类的复杂查询条件
- Hibernate使用原生SQL多表查询时字段名相同导致查询数据覆盖问题解决办法
- ASP“操作必须使用一个可更新的查询”问题的解决办法
- Microsoft JET Database Engine 错误 '80004005' 操作必须使用一个可更新的查询。问题解决办法
- 【小小问题集锦6之---查询条件非常复杂时解决效率不高的一个办法】
- 利用子查询解决复杂sql问题
- hibernate使用原生的sql,解决管理查询、结果集封装等问题
- 使用Ef查询出现的问题The cast to value type 'System.Boolean' failed because the materialized value is null.的解决方法