关于在IBatis中返回DataSet

在一个邮件列表的讨论中,了解了如何在IBatis.Net中返回DataSet以及一些相关的内容

        public static DataSet QueryForDataSet(string statementName, object paramObject)
        {
            DataSet ds 
= new DataSet();
            ISqlMapper mapper 
= GetMapper();
            IMappedStatement statement 
= mapper.GetMappedStatement(statementName);
            
if (!mapper.IsSessionStarted)
            {
                mapper.OpenConnection();
            }
            RequestScope scope 
= statement.Statement.Sql.GetRequestScope(statement, paramObject, mapper.LocalSession);
            statement.PreparedCommand.Create(scope, mapper.LocalSession, statement.Statement, paramObject);
            mapper.LocalSession.CreateDataAdapter(scope.IDbCommand).Fill(ds);

            
return ds;
        }


在这个过程中,我们还可以顺便得出获得SQL语句的方法

        public static string GetSql(string statementName, object paramObject)
        {
            ISqlMapper mapper 
= GetMapper();
            IMappedStatement statement 
= mapper.GetMappedStatement(statementName);
            
if (!mapper.IsSessionStarted)
            {
                mapper.OpenConnection();
            }
            RequestScope scope 
= statement.Statement.Sql.GetRequestScope(statement, paramObject, mapper.LocalSession);

            
return scope.PreparedStatement.PreparedSql;
        }

下面是我对文中内容的理解

并不是所有地方都要OO,IBatisJava.NET实现中都支持Dictionary类型的对象.DataTable因为有了DataView的支持而较IDictionary具有一些优势.如果我们需要对数据进行额外的排序或者过滤操作,那么DataTable会更方便一些.因此像这种返回DataSet的方法会使得IBatis更加易用.

但同时感觉,这种方法将IBatis打开了一个缺口,似乎背离了IBatis的设计初衷——创建一个优秀的“Persistence Ignorance domain model。比如现在,我们进行一次查询,获得“Plain Old CLR Objects”,看起来输入是与数据持久化相关的,而输出则完全集中在了领域模型上。

因此,返回DataSet的方法可能会导致不好的设计,从长远来看,也模糊了IBatis的初衷和意图。


posted @ 2007-05-30 09:55 Anders Cui 阅读(1119) 评论(18)  编辑 收藏 所属分类: 25-iBatis

  回复  引用  查看    
#1楼 2007-05-30 13:07 | steven love sunny      
正是想要的东西,没想到你这么快就写了Blog! :)
  回复  引用  查看    
#2楼 [楼主]2007-05-30 13:11 | Anders Cui      
@steven love sunny
希望能够有所帮助:)
  回复  引用  查看    
#3楼 2007-06-01 10:55 | steven love sunny      
你的GetMapper()方法获取的是当前的ISqlMapper吧,方法体的内容是怎样?我这在部署到具体应用系统中时会出错!
  回复  引用    
#4楼 2007-06-11 16:30 | saneblue [未注册用户]
为什么我运行到
mapper.LocalSession.CreateDataAdapter(scope.IDbCommand).Fill(ds);
这句就产生异常:
无法将类型为“IBatisNet.DataMapper.Commands.DbCommandDecorator”的对象强制转换为类型“System.Data.SqlClient.SqlCommand”。
我使用的是1.6.1版,而1.5.1版就可以。
  回复  引用  查看    
#5楼 [楼主]2007-06-11 20:07 | Anders Cui      
@saneblue
ISqlMapper mapper = GetMapper();
这行代码是取得要执行语句的ISqlMapper
看看这里对不对?
  回复  引用    
#6楼 2007-06-12 10:16 | saneblue [未注册用户]
取mapper是没问题的,关键是在1.6.1版中scope.IDbCommand返回的是一个IBatis.NET中自定义的DbCommandDecorator类,无法直接转为SqlCommand来使用,而1.5.1版中scope.IDbCommand直接返回跟当前Database Vendor相关的Command,不知道1.6.1版为什么这么设计。已经通过别的方式解决了。顺便说一句,我让IBatis.NET直接返回DataSet是为了做报表(主要是动态SQL),不是为了进行CRUD。

  回复  引用  查看    
#7楼 [楼主]2007-06-12 10:55 | Anders Cui      
@saneblue
嗯,我也是用来执行比较复杂的查询
  回复  引用    
#8楼 2007-06-13 00:46 | saneblue [未注册用户]
我的解决方法是通过mapper.LocalSession.CreateCommand返回一个当前Database Vendor相关的Command,然后把scope.IDbCommand中的SQL和参数传给这个Command,这样就成了。
  回复  引用  查看    
#9楼 [楼主]2007-06-13 10:19 | Anders Cui      
@saneblue
呵呵,这种方法也不错.
不知老兄对iBatis的DataAccess组件了解多吗?
  回复  引用    
#10楼 2007-06-13 23:44 | saneblue [未注册用户]
才用IBatis没多久,DataAccess还没用过,就用了DataMapper,连事务都是手工起的(用IBatis的事务)。

  回复  引用    
#11楼 2007-10-24 16:20 | 天道酬请 [未注册用户]
遇到有where条件的语句就无法正确显示sql了
传递“00001”给paramObject
却得到:Select statusName From tbStatus WHERE statusID = @param0

这是为什么呢??
  回复  引用  查看    
#12楼 [楼主]2007-10-24 16:59 | Anders Cui      
@天道酬请
这个问题我也看到了
还没看iBATIS的源码,也不了解如何去显示
建议你用log4net输出日志
这个肯定可以看到参数值的
  回复  引用    
#13楼 2007-10-25 09:01 | 天道酬请 [未注册用户]
找到原因了
/// <summary>
/// 通用得到参数化后的SQL(xml文件中参数要使用$标记的占位参?
/// </summary>

在XML文件中使用$
<dynamic prepend="WHERE">
<isParameterPresent>
qu_code=$QU_Code$
</isParameterPresent>
</dynamic>

就OK了~
  回复  引用  查看    
#14楼 [楼主]2007-10-25 09:31 | Anders Cui      
@天道酬请
这个不能算找到原因了 :)
$和#是两种不同的方式
$是字符串替换
#才是真正的参数
建议谨慎使用$
你可以看看我写的
http://www.cnblogs.com/anderslly/archive/2007/10/16/926517.html
  回复  引用    
#15楼 2007-10-26 09:00 | 天道酬请 [未注册用户]
我看了
还没找到其他的办法
只有尽量少用$了
  回复  引用    
#16楼 2008-02-16 01:56 | 匿名 [未注册用户]
当出现异常:
无法将类型为“IBatisNet.DataMapper.Commands.DbCommandDecorator”的对象强制转换为类型“System.Data.SqlClient.SqlCommand”。

//在iBatis1.5中有效:
mapper.LocalSession.CreateDataAdapter(scope.IDbCommand).Fill(ds);

//在1.6中有效
IDbCommand command = mapper.LocalSession.CreateCommand(CommandType.Text);
command.CommandText = scope.IDbCommand.CommandText;
mapper.LocalSession.CreateDataAdapter(command).Fill(ds);
  回复  引用  查看    
#17楼 2008-07-04 14:29 | ianc      
帮楼上补全一下:
//在iBatis1.5中有效:
//mapper.LocalSession.CreateDataAdapter(scope.IDbCommand).Fill(ds);

//在1.6中有效
IDbCommand command = mapper.LocalSession.CreateCommand(CommandType.Text);
command.CommandText = scope.IDbCommand.CommandText;

foreach (IDataParameter pa in scope.IDbCommand.Parameters)
{
command.Parameters.Add(new SqlParameter(pa.ParameterName,pa.Value));
}

mapper.LocalSession.CreateDataAdapter(command).Fill(ds);

  回复  引用    
#18楼 2008-08-02 23:44 | aha [未注册用户]
按接口编程,不直接使用SqlSqlserver相关的类,
再帮楼上再补全一下:
//在iBatis1.5中有效:
//mapper.LocalSession.CreateDataAdapter(scope.IDbCommand).Fill(ds);

//在1.6中有效
IDbCommand command = mapper.LocalSession.CreateCommand(CommandType.Text);
command.CommandText = scope.IDbCommand.CommandText;

foreach (IDataParameter pa in scope.IDbCommand.Parameters)
{
IDbDataParameter para = sqlMap.LocalSession.CreateDataParameter();
para.ParameterName = pa.ParameterName;
para.Value = pa.Value;
command.Parameters.Add(para);}

mapper.LocalSession.CreateDataAdapter(command).Fill(ds);

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  博客园首页

  新闻频道

  社区

  小组

  博问

  网摘

  闪存

  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-05-30 10:13 编辑过


相关链接: