.NETでのDB2 JDBCの鋸引き

NETがクロスプラットフォームになり、JAVAがさらに便利になりました。 しかし、私たちは共通の明るい未来に一緒に動いていますが、サポートする必要のある多くの継承された決定があります。 そして、これはジグソーパズルとファイルの助けを借りて可能ですが...



前に



現在、ドライバーはプロジェクトで必要な機能のみをサポートしています。 Wintegra.Dataプロジェクトにいつでも参加できます。



物語

(せっかちな人は、 Pilimアイテムに直接アクセスできます)



最近では、リレーショナルデータベースはどうやら誇大広告ではなく、誰にでもCAPシステムを提供します-速く、便利で、時には一貫性があり、スケーラブルです。 それにもかかわらず、インタープライズは古くて実績のあるソリューションに基づいており、その1つはBlue Giant-IBMのデータベースであり、その名前はDB2です。



適度に高速で信頼性が高く、OracleとMS SQLに劣らず、劣らない。 何かはありますが、何かはそうではありませんが、一般的にSQLは表記をサポートします(ただし、@犬に不快感がなかったわけではありません)



.NETのベースを使用するために、IBMは一般にODBCドライバーを提供しています。悪くはありませんが、ネイティブコードの小さなカートを使用しています。



一方、JAVAには、サードパーティdllを使用せずに完全に機能するドライバーがあり、その名前はJCC(JDBC 4.0ドライバー(db2jcc4.jar))です。



そして、IBMが.NETの下で「正しい」ダイバーを実装することを妨げる理由は明らかではありません。



.NET Coreはそれほど遠くないので、C#を使用してJAVAのコードを大量に書き直すのは奇妙に見えるので、1石で2羽の鳥を殺してはいけません。コードを残してJDBCドライバーを使用してください。



まず、 IKVM.NETを使用してjarをdllに変換し、.NETで使用します。 著者は、 Minecraftを安全に実行できると主張しています。 したがって、JDBCドライバーは問題を引き起こしませんでした。



必要なライブラリを作成するには、次のコマンドを実行するだけです:



ikvmc.exe -classloader:ikvm.runtime.AppDomainAssemblyClassLoader -target:library db2jcc4.jar db2jcc_license_cu.jar -out:db2jcc4.dll
      
      





必要なのは、作成したdllをソリューションに接続して使用することだけです。



.NETのJAVAコード
 using System; using com.ibm.db2.jcc; using java.sql; using Thread = java.lang.Thread; using Class = java.lang.Class; using String = System.String; using Connection = java.sql.Connection; using Statement = java.sql.Statement; using DriverManager = java.sql.DriverManager; using ResultSet = java.sql.ResultSet; namespace jdbc { class Program { static void Main(string[] args) { Class.forName( typeof(com.ibm.db2.jcc.DB2Driver).AssemblyQualifiedName, true, Thread.currentThread().getContextClassLoader()); String url = "jdbc:db2://192.168.72.135:50000/DB1:user=root;password=password;"; using (Connection conn = DriverManager.getConnection(url)) { String sql = "SELECT * FROM TABLE(VALUES( CAST( :p AS VARCHAR(100)) , 'It is work')) AS T(ID, LOG)"; using (var stmt = conn.prepareCall(sql)) { stmt.setString("p","1234"); using (ResultSet rs = stmt.executeQuery()) { while (rs.next()) { //Retrieve by column name String id = rs.getString("ID"); String log = rs.getString("LOG"); global::System.Console.WriteLine("LOG: " + id + " : " + log); } } } } } } }
      
      







ただし、.NET開発者はjava.langの形式の構文を高く評価するとは思いません。



のこぎり



ジグソーパズルとファイルを準備したら、必要な量の自転車を作成します。



 public sealed class Db2Connection : DbConnection, ICloneable
      
      





接続を作成してDapperを動作させるだけで十分です。



Db2connection
JAVAの世界からのちょっとした魔法



 static Db2Connection() { Class.forName( typeof(com.ibm.db2.jcc.DB2Driver).AssemblyQualifiedName, true, Thread.currentThread().getContextClassLoader()); }
      
      





JAVAとほぼ同じように、JDBCドライバーをロードします。



 Class.forName("com.ibm.db2.jcc.DB2Driver");
      
      





データベース接続は、1対1のJAVAです。



 connector = DriverManager.getConnection(_connectionString);
      
      





接続文字列はJDBCと同じであることに注意してください(ただし、必要に応じてDb2ConnectionStringBuilderを使用して独自の設定やODBCパラメータとの互換性を設定できます)。



 jdbc:db2://192.168.72.135:50000/DB1:currentSchema=DB01;user=root;password=password;fullyMaterializeLobData=true;DB2NETNamedParam=1;
      
      





サーバー、ポート、データベース、回線、ログイン、パスワードへの接続。 Blue Giant Webサイトで、JDBCおよびSQLJタイプ4接続用のIBM Data Server Driverの構成URL形式を確認できます



面白そうなものはすべて...



データベースにメリットをもたらすには、コマンドが必要です。



 public sealed class Db2Command : DbCommand, ICloneable
      
      





私がいじくり回さなければならなかったのはDapperです。



db2command
Dapperは、パラメーターXxmlDocumentのXML_BODYを不明瞭(:XML_BODY1 ,: XML_BODY2)に頑固に置き換えます -単純なレギュラーを作成する必要がありました。



 new Regex(@"\(:(?<n>\w+)\d+,:\1\d+\)");
      
      





はい、ただし好奇心D盛Dapper-ulongがSystem.ArgumentExceptionをスローしているため、TypeHandlerをファイルすることはできました。 しかし、第一に、ODBC上のラッパーはXmlDocumentで既に機能し、第二に、アプリケーションの開始時にフォームのマジックコマンドを使用していました。



 SqlMapper.AddTypeHandler(DapperULongHandler.Default);
      
      





常にエラーが発生します。



マジックメソッドは何回も



 internal static CallableStatement PrepareExecute(Db2Connection connection, string query, Db2ParameterCollection parameters)
      
      





準備されたクエリを返します。



特に注意すべきは、prepareStatement( PreparedStatement )の代わりにprepareCall( CallableStatement )を使用することの説明です。 位置パラメータの使用は簡単ですが、場合によっては便利ではないため、名前付きパラメータを使用するには追加の作業が必要になり、アクションがすぐに減少し、コードの複雑さが増します。 名前付きパラメーターが優先されました。これは、サーバーに送信される要求をデバッグする方が簡単であり、複数の要求が実行される場合にボーナスを与えるためです。



彼は魔法のために他の2つを使います。



マジックメソッド2



 internal static string PrepareCommandText(string query, Db2ParameterCollection parameters, ref int parameter)
      
      





位置パラメータを名前付きのものに置き換えます。



Dapperの小さな欺ceptionには2つの後藤がかかりました。 そして、それらなしで行うことは可能でしたが、解決策は単純であり、満足のいくものでした。



ref intパラメーター -Db2DataReaderおよびマルチクエリの実装に必要です。



最後の魔法の方法



 private static void PrepareParameters(CallableStatement stmt, Db2ParameterCollection parameters)
      
      





パラメータを設定します。



緑豊かなifと多くのメソッドを呼び出すstmt.setXXX(名前、



コマンドには、パラメーターが必要です。



 public sealed class Db2ParameterCollection : DbParameterCollection, IList<Db2Parameter>
      
      





 public sealed class Db2Parameter : DbParameter, ICloneable
      
      





Db2パラメーター
Dapperの場合、メソッドに対して少し魔法をかける必要があります。



 public override DbType DbType
      
      





型キャストに使用されるため、そうでない場合はインターフェイスを実装します。



そして、あなたはメソッドについて非常に注意する必要があります:



 public object Clone()
      
      





複数のリクエストのパラメーターのコピーを作成する必要があるため。



Db2ParameterCollection
メソッドの最適化がわずかに存在するため、注意が必要です。



 public override int IndexOf(string parameterName)
      
      



それ以外の実質的なものはありません



そして最後に:



 internal sealed class Db2DataReader : DbDataReader
      
      





JDBCを介したマルチクエリの実行の実装。



Db2datareader
おそらくこれは最善の解決策ではありませんが、なぜそうではありません。



最初に 、リクエストをサブクエリに分割する必要があります。 驚きのない単純な正規表現



 new Regex(@"(?<q>[^;]+);?");
      
      





次に 、サブクエリごとに独自のパラメータセットを準備する必要があります。 活用する



 new Regex(@"(?<n>:\w+)");
      
      



位置パラメータを名前付きパラメータに置き換えるための既におなじみのDb2Command.PrepareCommandTextメソッド(ボーナスとして:Dapperは通常、マルチリクエストで名前付きパラメータを処理できます)。



第三に 、あるコマンドから次のコマンドに移動するためのパブリックオーバーライドbool NextResult()の小さなハックです。

 var b = _statement.getMoreResults(); if (b) { _rs = _statement.getResultSet(); } else { _statement = PrepareStatementAndResultSet(); if (_statement != null) { _rs = _statement.executeQuery(); b = true; } }
      
      







まとめ



もちろん、プロジェクトはまだ完了していませんが、将来的には、db2jcc4.jar上のシェル実装を不要なスクワットなしの「通常の」.NETドライバー実装に置き換えたいという要望があります。



何が必要でしょうか?



まず、ユーザーのマシンにODBCドライバーをインストールすることはできませんが、ボリュームで勝つことはできません。

第二に、monoを使用してバックエンドをlinuxにゆっくり移行できます。 これは、 Dockerのささやきで非常に便利です。



そしてもちろん、ファンにとってはそれほど重要ではありません。



選択
 SELECT r.ID , r.INCOME , r.GU_CODE as GuCode , r.NO as No , r.DIVISION , d.NAME as DivisionName , u.LNAME || ' ' || u.FNAME || nvl(' ' || u.MNAME, '') as CreaterName , r.SIGNED , r.SIGNED_SYSUSER_ID as SignedID , su.LNAME || ' ' || su.FNAME || nvl(' ' || su.MNAME, '') as SignedName --, (select count(*) from PACK_ENTRY p where p.REGISTRY_ID = r.ID) as PackCount -- Use C# code --, (select count(*) -- from PACK_ENTRY p -- join FILE_ENTRY f on f.PACK_ID=p.ID -- where p.REGISTRY_ID = r.ID) as FileCount -- Use C# code -- TODO 2016-04-13 emiya:  .      REGISTRY_ENTRY , (select p.CLOSE_DATE from PACK_ENTRY p join REGISTRY_TO_PACK p2p on p2p.REGISTRY_ID = r.ID and p2p.PACK_ID = p.ID order by p.INCOME fetch first 1 rows only) as CloseDate , (select p.CATEGORY_ID from PACK_ENTRY p join REGISTRY_TO_PACK p2p on p2p.REGISTRY_ID = r.ID and p2p.PACK_ID = p.ID order by p.INCOME fetch first 1 rows only) as CategoryCode , (select l.SHORTNAME from PACK_ENTRY p join CATEGORY_LIST l on l.ID = p.CATEGORY_ID join REGISTRY_TO_PACK p2p on p2p.REGISTRY_ID = r.ID and p2p.PACK_ID = p.ID order by p.INCOME fetch first 1 rows only) as CategoryName , p2p.REGISTRY_ID , p.ID , p.INCOME , p.CLOSE_DATE as CloseDate , p.CATEGORY_ID as CategoryCode , l.SHORTNAME as CategoryName , p.GU_CODE as GuCode , p.NO , p.DIVISION , p.SYSUSER_ID as SysUserID , (select count(*) from FILE_ENTRY where PACK_ID = p.ID) as Count , r.SIGNED , p.PLACE , p2p.STATUS , p2p.NOTE from REGISTRY_ENTRY r join DIVISION d on d.CODE=r.DIVISION join SYSUSER u on u.ID=r.SYSUSER_ID LEFT JOIN SYSUSER su ON su.ID=r.SIGNED_SYSUSER_ID join REGISTRY_TO_PACK p2p on p2p.REGISTRY_ID = r.ID join PACK_ENTRY p on p.ID = p2p.PACK_ID join CATEGORY_LIST l on l.ID = p.CATEGORY_ID WHERE r.ID=? AND @DIVISION order by r.ID,p.GU_CODE,p.NO
      
      







NuGetのパッケージにリンクします。



All Articles