ibatisnetレビュー

最近ibatisnetのプロジェクトで使用される、いくつかは本当にすべてが、私は信じて、特にその動的SQL機能(動的SQL)のように、利便性の多くを変更した後に始めるために、最初にSQLを分離するこの方法に慣れていません動的なSQL関数が存在しない場合は、ibatisnet魅力が大幅に削減されます。ここでは、同様の問題が発生した場合、我々は長い間使用していないのibatisnetを議論することができ防ぐことはできませんが、いくつかのアイデアは単純すぎるかもしれない、私は問題のいくつかは、ibatisnetやソリューションに遭遇使用しているもので、批判を保管してください。

      まず、quaryfordatatableメソッドを追加私はibatisnetが実現ハッシュテーブルのIDictionaryのために戻るqueryfordictionary、データテーブル(またはデータセット)クエリメソッド、単一のエンティティクラスを返すために使用queryforobjectを返すことができます達成のArrayListのIListインターフェイスを返すqueryforlistに含まれていない非常に奇妙でした。あなたはまた、データのコレクションを返すことができますが、ビジネス層とプレゼンテーション層で使用するデータのこれらのコレクションは非常に困難であるが、この方法の性能をさらにいくつかの損失よりも悪い柔軟性のDataTable多くは、私はパフォーマンス要件が相対的に、非常に高くはないと思うだろう迅速な開発と容易なメンテナンスを実現することも可能です。この目的のために、私は次のことを達成するために、メソッドデータテーブルによって変換のDataReaderの元のシステムに直接戻され、ソースコードへの変更を最小限に抑えるquaryfordatatable方法を追加しました。
パブリッククラスsqlmapper:isqlmapper
{
...
公衆たSystem.Data.DataTable queryfordatatable(文字列statementname、オブジェクトparameterobject)

{
                  ...
                     試し 
                      {
                            imappedstatement声明= getmappedstatement(statementname)。
                            表= statement.queryfordatatable(セッション、statementname、parameterobject)。}
                     ...}
}

publicクラスのmappedstatement:imappedstatement

{

パブリックたSystem.Data.DataTable queryfordatatable(idalsessionセッション、文字列statementname、オブジェクトparameterobject) 
{
     ...
     たIDataReader = Command.ExecuteReaderリーダー();
         //ポジション1:後述する、実行可能なSQLステートメントのコマンドを変換し、 
トライ 
          {=表convertdatareadertodatatable(リーダ);
     }
      ...
}
プライベート静的データテーブルconvertdatareadertodatatable(IDataReaderのリーダー)
          {
              データテーブル=新しい新しいデータテーブルobjdatatable();
              INT = intfieldcount reader.fieldcount;
              のための(INT intCounter = 0; intCounter <intfieldcount; intCounter ++)
               {
                   objdatatable.columns.add(reader.getname(intCounter)、reader.getfieldtype(intCounter)) ;
              }
              objdatatable.beginloaddata();
              [] =新しい新しいobjvaluesは[intfieldcount]オブジェクトオブジェクト、
              一方(reader.Read())
               {
                   reader.getvalues(objvalues);
                   (trueにobjvalues)objdatatable.loaddatarow;
              }
              reader.Close();
              objdatatable .endloaddata();
              objdatatable返す;
         }
}

メインジョブが実行されるように、次のステップは、適切なインターフェースとisqlmapper imappedstatementにそれを追加することです。このステップは、コードを比較的簡単投稿されていません。>

 第二に、デバッグ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

おすすめ

転載: blog.csdn.net/weixin_34408717/article/details/93251746