如题。要返回一个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 commandtry{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对象相关推荐

  1. 深入分析ADO.NET中的DataSet对象

    ADO.NET是.net Framework SDK中用以操作数据库的类库的总称.而DataSet类则是ADO.NET中最核心的成员之一,也是各种开发基于.Net平台程序语言开发数据库应用程序最常接触 ...

  2. Asp.net 用DataSet对象更新数据(SqlDataAdapter) DataTable加主键

      私の青い色スペース 专注于.NET,认真把握好生命的每一秒,让每天都过的有意义..!     常用链接 我的随笔 我的评论 我参与的随笔 留言簿(1) 给我留言 查看公开留言 查看私人留言 我参与 ...

  3. 浅谈ASP.net中的DataSet对象

    在我们对数据库进行操作的时候,总是先把数据从数据库取出来,然后放到一个"容器"中,再通过这个"容器"取出数据显示在前台,而充当这种容器的角色中当属DataSet ...

  4. XML 与DataSet 对象的关系

    在.NET Framework 中,经常使用XML 作为存储和传输各种数据的格式. DataSet 中的数据可以转换成XML 的形式来表示和存储. 我们可以使用XML 对象同步和转换DataSet 的 ...

  5. C# 实现DataTable、DataSet与XML互相转换

    /** <summary>/// 把DataSet.DataTable.DataView格式转换成XML字符串.XML文件/// </summary>public class ...

  6. 使用DataSet对象添加记录

    使用DataSet对象添加记录 使用DataSet对象添加记录 步骤: ●创建Connection对象 ●创建DataAdapter对象 ●通知数据适配器我们要使用的连接 ●创建一个DataSet对象 ...

  7. android webapi 返回html 代码,ANDROID调用VS2013 ASP.NET WEBAPI 返回DATATABLE 注意

    VS2013 WEBAPI项目直接就可以返回DATATABLE,并且IIS会处理好返回JSON字符串,不需要在服务端做任何额外的转换工作. 但我在ANDROID里调用时发现不能把JSON字符串转换成J ...

  8. 玩转肺癌目标检测数据集Lung-PET-CT-Dx ——③整理、验证数据,建立Dataset对象

    文章目录 数据整理 整理出所有的dcm文件 整理出所有的xml标注文件 整理数据①--舍弃错误的标注文件 整理数据②--两个标注文件指向同一个目标图片的情况 封装函数,传入xml文件,显示标注效果 整 ...

  9. 关于在DataTable中执行DataTable.Select(条件)返回DataTable的解决方法

    在实际编程工程中,常常遇到这样的情况:DataTable并不是数据库中的,或者DataTable尚未写到数据库,或者从数据库中读出的DataTable已经在本地被改动,又没有写回数据库(可能还要作其他 ...

最新文章

  1. 人在职场,干得好真的不如汇报得好?
  2. CLR via C# (二)
  3. 收藏一个在线思维导图的制作网站
  4. 单页面与多页面的优缺点
  5. 华为机试HJ12:字符串反转
  6. 计蒜客网站 ACM-ICPC亚洲区赛题
  7. iMazing备份的详细教程
  8. 带你玩转IntelliJ IDEA 使用教程(2019图文版)
  9. 腾讯翻译君在线翻译怎么翻译整个文件_腾讯文档:在线多人协作文档工具
  10. 清华团队夺冠清华-新南威尔士中澳数据科学大赛!跨学科交叉人才走出国门
  11. 眼睛到底是冷敷好还是热敷好?敷眼睛是个技术活!
  12. 一个简单的例子来理解监督学习和非监督学习及其区别
  13. java库存同步思路_这个是真的厉害,高并发场景下的订单和库存处理方案,讲的很详细了!...
  14. Linux安装MySQL5.7 启动时ERROR! The server quit without updating PID file (/data/mysql/mysql.pid).
  15. UCGUI使用外部字库芯片显示汉字
  16. ECS.Day3笔记
  17. Google新鲜技巧玩法及最新揭秘
  18. HyperTerminal 超级终端设置TCP/IP Client和TCP/IP Server
  19. 京东末位淘汰:为什么末位淘汰不适合用在软件研发团队?(特朗普亲身示范正确做法)
  20. 二、Ubuntu16.04安装搜狗wps

热门文章

  1. ++i 和 i++的实现
  2. STL的deque容器
  3. 经典C语言程序100例之二一
  4. MapReduce多个job同时使用的方式(从网上找到的案例,原始博文:http://www.cnblogs.com/yjmyzz/p/4540469.html)
  5. dubbo控制中心部署,权重配置,以及管控台中各个配置的简单查看
  6. 跟益达学Solr5之使用Tika从PDF中提取数据导入索引(转字:http://www.tuicool.com/articles/JfUfaey)
  7. Sturt2做表单重复提交
  8. python 摄像头录制帧率_基于opencv和python的可变帧速率IP摄像机视频记录
  9. Linux(Ubuntu,Cent OS)环境安装mkfontscale mkfontdir命令以及中文字库
  10. 图像处理基本算法 形状特征