iBatis.Net实现返回DataTable和DataSet对象
如题。要返回一个ADO.NET对象好像没有使用ORM的必要,而且从编程的角度看这样的实现一点也不OO,但是实际的开发场景中还是会碰到这种需求的。下面我就借鉴前人的经验,结合实际的示例,再总结一下。如果您认真看完,应该可以体会得到我的一些尝试,而不是人云亦云的照搬代码。
1、获得DbCommand对象
对于SQL语句,方法如下:

/// <summary>
/// SQL语?句?,?获?取?DbCommand
/// </summary>
/// <param name="sqlMapper"></param>
/// <param name="statementName"></param>
/// <param name="paramObject"></param>
/// <returns></returns>
protected virtual IDbCommand GetDbCommand(ISqlMapper sqlMapper, string statementName, object paramObject)
{
IStatement statement = sqlMapper.GetMappedStatement(statementName).Statement;
IMappedStatement mapStatement = sqlMapper.GetMappedStatement(statementName);
ISqlMapSession session = new SqlMapSession(sqlMapper); if (sqlMapper.LocalSession != null)
{
session = sqlMapper.LocalSession;
}
else
{
session = sqlMapper.OpenConnection();
} RequestScope request = statement.Sql.GetRequestScope(mapStatement, paramObject, session);
mapStatement.PreparedCommand.Create(request, session as ISqlMapSession, statement, paramObject);
IDbCommand cmd = session.CreateCommand(CommandType.Text);
cmd.CommandText = request.IDbCommand.CommandText;
//return request.IDbCommand;
return cmd;
}
对于存储过程,因为对于参数类型的不同,需要多几步处理(因为需要多维护一个参数字典和其对应的ParameterDirection字典):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
/// <summary> /// 获取DbCommand,主要是针对存储过程 /// </summary> /// <param name="sqlMapper"></param> /// <param name="statementName"></param> /// <param name="paramObject">参数</param> /// <param name="dictParam">参数字段</param> /// <param name="dictParmDirection">ParameterDirection字典</param> /// <param name="cmdType"></param> /// <returns></returns> protected virtual IDbCommand GetDbCommand(ISqlMapper sqlMapper, string statementName, object paramObject, IDictionary dictParam, IDictionary< string , ParameterDirection> dictParmDirection, CommandType cmdType) { if (cmdType == CommandType.Text) { return GetDbCommand(sqlMapper, statementName, paramObject); } IStatement statement = sqlMapper.GetMappedStatement(statementName).Statement; IMappedStatement mapStatement = sqlMapper.GetMappedStatement(statementName); ISqlMapSession session = new SqlMapSession(sqlMapper); if (sqlMapper.LocalSession != null ) { session = sqlMapper.LocalSession; } else { session = sqlMapper.OpenConnection(); } RequestScope request = statement.Sql.GetRequestScope(mapStatement, paramObject, session); mapStatement.PreparedCommand.Create(request, session as ISqlMapSession, statement, paramObject); IDbCommand cmd = session.CreateCommand(cmdType); cmd.CommandText = request.IDbCommand.CommandText; if (cmdType != CommandType.StoredProcedure || dictParam == null ) { return cmd; } foreach (DictionaryEntry de in dictParam) //存储过程 { string key = de.Key.ToString(); IDbDataParameter dbParam = cmd.CreateParameter(); dbParam.ParameterName = key; dbParam.Value = de.Value; if (dictParmDirection != null && dictParmDirection.ContainsKey(key)) { dbParam.Direction = dictParmDirection[key]; //ParameterDirection } cmd.Parameters.Add(dbParam); } return cmd; } |
代码写得可能还有改进的必要,有需要从事这方面开发的童鞋,如果您看着有更好的办法请不吝赐教。
备注:
a、对于1.6.1之前的版本,获得命令的方式可以通过RequestScope的IDbCommand属性,但是1.6.1版本的IDbCommand属性返回的是IBatisNet.DataMapper.Commands.DbCommandDecorator对象,您可以注释代码验证一下。
b、网上有些文章贴的方法返回的DbCommand对象都是对于拼接SQL语句而言,没有实现获取存储过程的DbCommand(有参数无参数的都要考虑)。本文在原有资料的基础上,尝试着做出改进,目前支持SQL语句和存储过程。
2、返回DataSet对象
通过SQL语句,获取DataSet:
1
2
3
4
5
|
public DataSet GetDSPerson( int id) { string sql = this .GetRuntimeSql( this .SqlMapper, this .GetStatementName( "GetDSPerson" ), id); return this .QueryForDataSet( this .SqlMapper, this .GetStatementName( "GetDSPerson" ), id); } |
XML配置:
1
2
3
4
|
< select id="GetDSPerson" parameterClass="int" resultClass="System.Data.DataSet"> < include refid="CommonPersonColumns4Select"></ include > WHERE 1=1 AND Id=$id$ </ select > |
客户端的调用:
1
2
3
|
int id = 1; DataSet ds = ServiceFactory.CreatePersonService().GetDSPerson(id); Console.WriteLine(ds.GetXml()); |
执行结果返回如下:
3、返回DataTable对象
a、通过SQL语句

/// <summary>
/// 通?用?的?执′行DSQL语?句?以?DataTable的?方?式?得?到?返う?回?的?结á果?(xml文?件t中D参?数簓要癮使?用?$标括?记?的?占?位?参?数簓)
/// </summary>
/// <param name="sqlMapper"></param>
/// <param name="statementName"></param>
/// <param name="paramObject"></param>
/// <returns></returns>
protected virtual DataTable QueryForDataTable(ISqlMapper sqlMapper, string statementName, object paramObject)
{
DataSet ds = new DataSet();
bool isSessionLocal = false;
IDalSession session = sqlMapper.LocalSession;
if (session == null)
{
session = new SqlMapSession(sqlMapper);
session.OpenConnection();
isSessionLocal = true;
} IDbCommand cmd = GetDbCommand(sqlMapper, statementName, paramObject);//SQL text command try
{
cmd.Connection = session.Connection;
IDbDataAdapter adapter = session.CreateDataAdapter(cmd);
adapter.Fill(ds);
}
finally
{
if (isSessionLocal)
{
session.CloseConnection();
}
} return ds.Tables[0];
}
这个相对简单,因为前面2中已经得到了DataSet,DataTable的提取就轻而易举了。
b、通过含OUTPUT参数的存储过程
这个地方主要就是改进后的GetDbCommand重载方法的使用,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
/// <summary> /// 查询返回DataTable,对于包括OUTPUT参数的存储过程同样适用 /// </summary> /// <param name="sqlMapper"></param> /// <param name="statementName"></param> /// <param name="paramObject">参数</param> /// <param name="dictParam">参数字典</param> /// <param name="dictParamDirection">ParameterDirection字典</param> /// <param name="htOutPutParameter">返回的Output参数值哈希表</param> /// <returns></returns> protected virtual DataTable QueryForDataTable(ISqlMapper sqlMapper, string statementName, object paramObject, IDictionary dictParam, IDictionary< string , ParameterDirection> dictParamDirection, out Hashtable htOutPutParameter) { DataSet ds = new DataSet(); bool isSessionLocal = false ; ISqlMapSession session = sqlMapper.LocalSession; if (session == null ) { session = new SqlMapSession(sqlMapper); session.OpenConnection(); isSessionLocal = true ; } IDbCommand cmd = GetDbCommand(sqlMapper, statementName, paramObject, dictParam, dictParamDirection, CommandType.StoredProcedure); //存储过程 try { cmd.Connection = session.Connection; IDbDataAdapter adapter = session.CreateDataAdapter(cmd); adapter.Fill(ds); } finally { if (isSessionLocal) { session.CloseConnection(); } } htOutPutParameter = new Hashtable(); foreach (IDataParameter parameter in cmd.Parameters) { if (parameter.Direction == ParameterDirection.Output) { htOutPutParameter[parameter.ParameterName] = parameter.Value; } } return ds.Tables[0]; } |
测试的存储过程如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
USE [TestDb] GO --根据id查询某人 并返回所有人中,最大体重,最小身高 CREATE PROCEDURE [dbo].[usp_GetPersonById] @MaxWeight float output , @MinHeight float output , @Id int AS BEGIN SELECT Id, FirstName, LastName, Weight, Height FROM Person WHERE Id=@Id SET @MaxWeight= ( SELECT MAX (Weight) FROM Person) SET @MinHeight= ( SELECT MIN (Height) FROM Person) END |
本文的示例测试通过,返回的结果如下:
从上图中,我们可以看到最大体重是200,最矮身高是177。
4、小结和注意点
a、返回ADO.NET对象的方法,iBatis拼接的SQL语句必须通过而不是熟悉的#符号连接,这个会有众所周知的SQL注入的风险。
b、我还没有实际尝试过最新版本的iBatis,对于较新的版本,不知道本文的方法还适不适用。
c、我参考这篇文章的时候,发现说有一个无法返回output参数的问题。我尝试着重现这个问题。功夫不负有心人,本文示例中我已经实现好了,给自己鼓励一下。
iBatis.Net实现返回DataTable和DataSet对象的更多相关文章
- IBatis.Net使用总结(二)-- IBatis返回DataTable/DataSet(网上例子的集合)
IBatis返回DataTable,DataSet ibatis.net QueryForDataTable 完整的为ibatis.net 引入datatable支持要改动很多地方,所以描述的是最小化 ...
- LINQ返回DataTable类型 list转dataset 转换为JSON对象
using System.Web.Script.Serialization; using System.Collections.Generic; using System.Reflection; us ...
- IBatis.Net使用总结(三)-- IBatis实现分页返回数据和总数
IBatis 分页,这里没有使用其他插件,只使用最原始的方法. 输入参数: int currentPage 当前页 int pageSize 每页大小 Hashtable findCondition ...
- C#与数据库访问技术总结(十六)之 DataSet对象
DataSet对象 DataSet对象可以用来存储从数据库查询到的数据结果,由于它在获得数据或更新数据后立即与数据库断开,所以程序员能用此高效地访问和操作数据库. 并且,由于DataSet对象具有离线 ...
- 浅谈ASP.net中的DataSet对象
在我们对数据库进行操作的时候,总是先把数据从数据库取出来,然后放到一个"容器"中,再通过这个"容器"取出数据显示在前台,而充当这种容器的角色中当属DataSet ...
- C# 实现DataTable、DataSet与XML互相转换
/**//// <summary> /// 把DataSet.DataTable.DataView格式转换成XML字符串.XML文件 /// </summary> public ...
- DataTable与DTO对象的简易转换类
在web开发过程中,有时候为了数据传输的方便,比如:后台需要更新前端的ViewModel,此时我们定义一个与前端ViewModel结构一样的DTO对象,从数据层获取数据后,将数据封装成DTO然后序列化 ...
- .Net中List<T> 泛型转成DataTable、DataSet
在开发过程过程中有时候需要将List<T>泛型转换成DataTable.DataSet,可以利用反射机制将DataTable的字段与自定义类型的公开属性互相赋值. 1.List<T& ...
- 将Json数据转换为ADO.NET DataSet对象
Json数据转换为ADO.NET DataSet其实方法有很多,Newtonsoft.Json也提供了DataSet的Converter用以转换Json数据.但是有些情况下DataSet Conver ...
随机推荐
- 【读书笔记】iOS-NSData
Cocoa为我们提供了NSData类,该类包装了大量字节,你可以获得数据的长度和指向字节起始位置的指针,因为NSData是一个对象,适用于常规的内存管理行为.因此,如果将数据块传递给一个函数或方法,可 ...
- mac 下安装android studio(转)
1)下载最新jdk8,下载android studio 2)安装jdk8,双击jdk8的安装包,将jdk8的安装包拖到Application,可能会出现这种问题:要求Mac OS X10.7.3或更高 ...
- Java从零开始学四十五(Socket编程基础)
一.网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输. 在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可 ...
- android的屏幕保持常亮
1.Wake Lock是一种锁的机制 在Manifest.xml文件里面用user-permission声明.代码如下: 这种方法,在安装apk时,系统会提示安装人是否允许使用禁止休眠功能. < ...
- Windows Server 2008 下ASP程序连接ORACLE数据库驱动错误
今天开发那边升级.改造系统过程中,在测试服务器碰到关于ASP程序连接ORACLE数据库的小问题,虽然是小问题,但是整起来真要命啊,花了不少时间,主要是ASP程序啊,这种上古神器,哥还是当年毕业的时候弄 ...
- MySQL之ALTER
1:删除列 ALTER TABLE [表名字] DROP [列名称] 2:增加列 ALTER TABLE [表名字] ADD [列名称] INT NOT NULL COMMENT '注释说明' 3:修 ...
- cxf数据压缩
一.HTTP数据的压缩 在http协议中当content-encoding对应的值为gzip,deflate,x-gzip,x-deflate时,数据是经过了压缩之后再进行传输的.有些时候我们当我们传 ...
- java代码调用oracle存储过程
一.简介 与调用mysql存储过程类型过程都是如下 1.创建连接 Connection conn = DriverManager.getConnection(url, user, password); ...
- Linux SELinux命令
getsebool与setsebool工具 说明:SELinux规范了许多boolean数值清单档案,提供开启或关闭功能存取项目,而这些值都存放在/selinux/booleans/目录内相关档案,这 ...
- cmd获取系统时间
查看时间格式: echo %date% echo %time% 通过%date:~5,2%来组合得出当前日期,组合的效果为yyyymmdd,date命令得到的日期格式默认为yyyy-mm-dd,通过% ...