ibatisnet Reviews

Recently used in a project of ibatisnet, some really not used to this way of separating out the sql at the beginning, to get started after that everything changed a lot of convenience, especially like its dynamic sql function (dynamic sql), I believe If there is no dynamic sql function, ibatisnet charm will be greatly reduced. Here is what I use some of the problems encountered ibatisnet and solutions, if you have encountered a similar problem, do not prevent we can discuss the use ibatisnet not long, some ideas might be too simple, please keep criticism .

      First, add quaryfordatatable method I have been very strange not included in ibatisnet can return datatable (or dataset) query method, queryforobject used to return a single entity class, queryforlist return achieved arraylist ilist interface, queryfordictionary return for the realization hashtable idictionary. Although you can also return a collection of data, but these collections of data to use in the business layer and the presentation layer is very difficult, flexibility datatable lot worse than even some loss of performance of the method will, I think the performance requirements are not very high, relative to achieve rapid development and easy maintenance is also acceptable. To this end, I added a quaryfordatatable way to minimize changes to the source code, I returned directly to the original system of datareader converted by a method datatable, to achieve the following:
public class sqlmapper : isqlmapper
{

public system.data.datatable queryfordatatable (string statementname, object parameterobject)

{
                  …
                     try 
                      {
                            imappedstatement statement = getmappedstatement(statementname);
                            table = statement.queryfordatatable (session,statementname, parameterobject);                }
                     …}
}

public class mappedstatement : imappedstatement

{

public system.data.datatable queryfordatatable (idalsession session,string statementname, object parameterobject) 
{
     ...
     IDataReader = Command.ExecuteReader Reader ();
         // Position 1: Convert the sql statement command can be executed, described later; 
the try 
          {= Table convertdatareadertodatatable (Reader);
     }
      ...
}
Private static DataTable convertdatareadertodatatable (IDataReader Reader)
          {
              DataTable = new new DataTable objdatatable ();
              int = intfieldcount reader.fieldcount;
              for (int intCounter = 0; intCounter <intfieldcount; intCounter ++)
               {
                   objdatatable.columns.add (reader.getname (intCounter), reader.getfieldtype (intCounter)) ;
              }
              objdatatable.beginloaddata ();
              Object [] = new new objvalues Object [intfieldcount];
              the while (reader.Read ())
               {
                   reader.getvalues (objvalues);
                   objdatatable.loaddatarow (objvalues, to true);
              }
              reader.Close ();
              objdatatable .endloaddata ();
              return objdatatable;
         }
}

so that the main job is done, the next step is to add the appropriate interfaces and isqlmapper imappedstatement it. This step is relatively simple, not posted the code:>

 Second, the debugging ibatisnet

    多数情况下,ibatisnet并不会把配置文件中的语句和参数拼成可以直接执行的sql语句(只有在使用$符号标识参数时会这样),而是把它们构造为一 个实现idbcommand接口的对象,如果使用sql server数据库,也就是sqlcommand对象,配置文件中的语句作为commandtext的值,参数添加到为sqlcommand中的 parameters集合中。然后通过执行idbcommand返回结果。

     执行sql语句出错时,我喜欢把它放到查询分析器中调试,通过查询分析器的语法分析及执行结果检查sql语句。但在ibatisnet中所有的数据库操作 都是通过idbcommand对象来执行的,如果没有参数还好些,直接在中断或输出中使用idbcommand.commandtext得到sql语句就 可以了。但是更多时候都是包含了多个参数,这时再想得到完整的可执行的sql语句是非常让人头疼的一件事。幸好我们有办法可以弥补这个问题,原理很简单, 因为在idbcommand对象的内部它也并未直接拼接所有的参数,而是利用sql server中的sp_executesql存储过程执行参数化查询。通过跟踪数据库可以证实这一点。那我们就可以根据idbcommand对象的属性值 自己构造一个使用sp_executesql的sql语句,未经过全面测试的代码如下:

文件mappedstatement.cs中的位置1处

#if  (debug)
system.data.sqlclient.sqlcommand com
= (system.data.sqlclient.sqlcommand)command;

                   
string  sql = " execute sp_executesql n' "  +  com.commandtext.replace( " ' " , " '' " +  " ' "  ;

                   
if  (com.parameters.count > 0 )

                   
{
                       sql 
+="<br>,n'";
                       
for (int i=0;i<com.parameters.count;i++)
                       
{                            system.data.sqlclient.sqlparameter para=com.parameters[i];

                            sql 
+=para.parametername + " " + para.sqldbtype.tostring() + "" ;

                       }

                       sql
=sql.substring(0,sql.length-1);
                       sql 
+="'<br>,"r"n";
                       
for (int i=0;i<com.parameters.count;i++)
                       
{                            system.data.sqlclient.sqlparameter para=com.parameters[i];
                            sql 
+=para.parametername + "='" + para.value + "'," ;
                       }


                       sql
=sql.substring(0,sql.length-1);        
                   }
 
                   sql 
+= " <br> " ;                   system.web.httpcontext.current.session[ " executablesql " ] = sql;
#endif
idatareader reader 
=  command.executereader();

该结果我是准备显示在页面上的,所以换行使用了<br>,然后把结果保存在会话中以方便在表示层根据需要获取该值。
最后在表示层中使用一个可切换可见状态的div控件显示生成的语句即可。 

三、ibatisnet中的分页

ibatisnet中虽然提供了分页机制,但和dategrid的 自动分页原理相似,都是在查询出全部数据后再从结果集中截取需要的子集,这种方法根本无法应用在数据里稍大的系统中。到目前为止解决分页问题的最好方法依 然是使用存储过程。ibatisnet支持存储过程,你可以通过ibatisnet调用分页存储过程,这样,这个问题讨论基本就应该结束了。

不过还一个小问题,如果使用存储过程将无法使用ibatisnet 中的动态sql功能,这对于系统中需要分页的地方较少或动态sql利用不多的情况来说,这点损失可以忽略不计了。但本着钻牛角尖就钻到底的精神,我一直想 找出更好的解决方案来。写本文时我只是有一个初步的想法,还未完全实现,这里先把我的思路写出来让大家提提意见。

关于存储过程分页的方案在网上已经很多了,这篇文章是内容比较全的,而且还包含了对每个存储过程的测试:http://www.codeproject.com/aspnet/paginglarge.asp,这是个老外写的,如果大家看着别扭也没关系,我的朋友tonyqus很早就把它翻译过来了:http://tonyqus.cnblogs.com/archive/2006/03/12/344357.html。附件中包含了针对每种方案的完整实现,而且都是通用化的,也就是说适合绝大多数sql语句的分页。存储过程的参数也都相同,下面是其中一个存储过程的标头:

create procedure paging_asc_desc (
@tables varchar(1000),
@pk varchar(100),
@sort varchar(200) = null,
@pagenumber int = 1,
@pagesize int = 10,
@fields varchar(1000) = '*',
@filter varchar(1000) = null,
@group varchar(1000) = null)
as

这样,我们只需要把ibatisnet生成的语句按上面部分分解然 后调用即可。这样问题的关键就转变为如何得到最终的sql语句,这在ibatisnet中是比较容易实现的。首先,在配置文件中使用$符号标识参数可以直 接把参数拼到sql语句中,也就是说直接使用idbcommand.commandtext即可得到最终可以执行的sql语句。或者,如果使用#符号标识 参数,也可以通过一个简单的方法把idbcommand对象的值拼成可执行的sql语句。剩下的就是需要把该sql语句分解成符合要求的各个部分了。在这 个问题上我还没找到比较好的办法,对于较为标准的sql语句比较好分解,如果遇到复杂的sql语句分解起来可能比较麻烦,这个问题就留给看到此文的朋友 吧,不过我想这种情况不是太多,即使遇到特殊处理一下就可以了。

为了调用方便,可以在ibatisnet中增加一个查询接口,如 queryforpaginglist(string statementname, object parameterobject,int pagenumber,int pagesize),如果使用对参数化查询手动拼接sql的方法可以不用修改原配置文件中的参数化查询,且可以对同一个mapped statement同时使用不分页和分页两种查询方法。

四、其他一些小技巧

     对于把表名作为参数或者在in关键字中作为使用参数的情况,可以使用$符号标识参数,但要注意在赋值之前先检查是否有sql注入的危险。
     使用一些代码生成工具可以按表生成ibatisnet使用的配置文件。为了能在修改表结构后还可以使用代码生成工具重新生成,建议不要修改自动生成的配置文件,如果需要添加操作,可以创建新的配置文件。
     ibatisnet项目源码中已经包含了配置文件的架构文件(.xsd),把它放到vs中相应目录可利用vs的智能感应,并对配置文件进行验证。不同的vs版本,对应的目录也不同:
c:"program files"microsoft visual studio 8"xml"schemas for vs.net 2005
c:"program files"microsoft visual studio .net 2003"common7"packages"schemas"xml for vs.net 2003
c:"program files"microsoft visual studio .net"common7"packages"schemas"xml for vs.net 2002

转载于:https://www.cnblogs.com/zyfking/archive/2009/01/19/1378502.html

Guess you like

Origin blog.csdn.net/weixin_34408717/article/details/93251746