Open棟梁 wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。

目次

概要

配列バインドをサポートしていないデータプロバイダでの
大量データ処理(バッチ更新処理)の実装のために、バッチクエリ作成支援機能を提供しています。

  • SQLUtilityクラスの、GetInsertSQLParts、GetUpdateSQLPartsメソッドを使用すると、バッチ処理用のSQLパーツを生成できます。
    • Datatableを渡すことで複数行に渡るINSERT文、UPDATE文を生成します。
  • BaseDamクラス の、ExecGenerateSQLメソッドを使用すると、SQLを実行しないで、SQLのみ生成できます。
    • このSQLを使用して、(SQL実行のラウンドトリップを抑えた)バッチ処理を容易に実装できます。

双方とも、パタメタ数制限をクリアするために、String型パタメタは文字列展開してから実行します。

SQLUtilityクラス

  • SQLUtilityクラスの、GetInsertSQLParts、GetUpdateSQLPartsメソッドを使用すると、バッチ処理用のSQLパーツを生成できる。
  • このSQLパーツを使用して、(SQL実行のラウンド・トリップを抑えた)インサートとアップデートのバッチ処理を容易に実装できる。

GetInsertSQLPartsメソッド

サンプル・コード

以下、バッチ・インサートのサンプル・コード。

// データテーブル作成
DataTable dt = new DataTable();

・・・データ作成コードは省略・・・

// SQLパーツの生成
// 第2・3引数は省略可能(第2の既定値はnvarchar)。
SQLUtility su = new SQLUtility(DbEnum.DBMSType.SQLServer, "varchar", "yyyy/MM/dd");
string[] strs = su.GetInsertSQLParts(dt);

// SQLパーツの組立
string collist = "";
StringBuilder sb = new StringBuilder();

foreach (string str in strs)
{
  if (string.IsNullOrEmpty(collist))
  {
    collist = str;
  }
  else
  {
    sb.Append(str + ",");
  }
}

// 最後のカンマを削る。
string temp = sb.ToString();
temp = temp.Substring(0, temp.Length - 1);

// 共通Daoでバッチ・インサート
CmnDao cd = new CmnDao(this.GetDam());
cd.SQLText = string.Format("INSERT INTO XXX{0} VALUES{1}", collist, temp);
cd.ExecInsUpDel_NonQuery();

実行されるSQL

INSERT INTO XXX
  ([aaa],[bbb],[ccc],[ddd],[eee],[fff])
VALUES
  (Convert(varchar,'a'),Convert(varchar,'aaa'),0xFF,0xFFFFFF,'2013/09/20',1),
  (Convert(varchar,'b'),Convert(varchar,'bbb'),0xFE,0xFEFEFE,'2013/09/20',2),
  (Convert(varchar,'c'),Convert(varchar,'ccc'),0xFD,0xFDFDFD,'2013/09/20',3)

GetUpdateSQLPartsメソッド

サンプル・コード

以下、バッチ・アップデートのサンプル・コード。

// データテーブル作成
DataTable dt = new DataTable("XXX");

・・・データ作成コードは省略・・・

// SQLパーツの生成
// 第2・3引数は省略可能(第2の既定値はnvarchar)。
SQLUtility su = new SQLUtility(DbEnum.DBMSType.SQLServer, "varchar", "yyyy/MM/dd");
string[] strs = su.GetUpdateSQLParts(dt, new string[] { "aaa" });

// SQLパーツの組立
StringBuilder sb = new StringBuilder();

foreach (string str in strs)
{
  sb.Append("UPDATE " + dt.TableName + " " + str + ";");
}

// 共通Daoでバッチ・アップデート
CmnDao cd = new CmnDao(this.GetDam());
cd.SQLText = sb.ToString();
cd.ExecInsUpDel_NonQuery();

実行されるSQL

UPDATE XXX
  SET [bbb] = Convert(varchar,'aaa'),[ccc] = 0xFF,[ddd] = 0xFFFFFF,[eee] = '2013/09/20',[fff] = 1
  WHERE [aaa] = Convert(varchar,'a');
UPDATE XXX
  SET [bbb] = Convert(varchar,'bbb'),[ccc] = 0xFE,[ddd] = 0xFEFEFE,[eee] = '2013/09/20',[fff] = 2
  WHERE [aaa] = Convert(varchar,'b');
UPDATE XXX
  SET [bbb] = Convert(varchar,'ccc'),[ccc] = 0xFD,[ddd] = 0xFDFDFD,[eee] = '2013/09/20',[fff] = 3
  WHERE [aaa] = Convert(varchar,'c');

BaseDam?クラス

  • BaseDam?クラスの、ExecGenerateSQLメソッドを使用すると、SQLを実行しないで、SQLのみ生成できる。
  • このSQLを使用して、(SQL実行のラウンドトリップを抑えた)バッチ処理を容易に実装できる。

ExecGenerateSQLメソッド

サンプル・コード

以下、バッチ・インサートのサンプル・コード(詳細は、RerunnableBatch_sample2を参照)。

//Orders2テーブルに複数件まとめて追加する。
StringBuilder sb = new StringBuilder();

for (int index = 0; index < dataTable.Rows.Count; index++)
{
  DataRow row = dataTable.Rows[index];    //1件分のデータ

  //todo:編集処理など

  // ↓DBアクセス-----------------------------------------------------
  // 自動生成Daoを生成
  DaoOrders2 dao = new DaoOrders2(this.GetDam());

  // パラメータを設定
  dao.PK_OrderID = row["OrderID"];
  dao.CustomerID = row["CustomerID"];
  dao.EmployeeID = row["EmployeeID"];
  ・・・
  dao.ShipRegion = row["ShipRegion"];
  dao.ShipPostalCode = row["ShipPostalCode"];
  dao.ShipCountry = row["ShipCountry"];

  // 自動生成Daoを実行
  sb.Append(dao.ExecGenerateSQL(
    "DaoOrders2_S1_Insert.sql", new SQLUtility(DbEnum.DBMSType.SQLServer)) + ";\r\n");

  // ↑DBアクセス-----------------------------------------------------
}

// 共通Daoでバッチ・インサート
CmnDao cd = new CmnDao(this.GetDam());
cd.SQLText = sb.ToString();
cd.ExecInsUpDel_NonQuery();

実行されるSQL

INSERT INTO [Orders2]
  ( [OrderID], [CustomerID], [EmployeeID], [OrderDate], [RequiredDate], [ShippedDate], [ShipVia],
    [Freight], [ShipName], [ShipAddress], [ShipCity], [ShipRegion], [ShipPostalCode], [ShipCountry] )
VALUES
  ( 10248, Convert(nvarchar,'VINET'), 5, '1996/07/04 00:00:00.000', '1996/08/01 00:00:00.000', '1996/07/16 00:00:00.000',
    3, 32.3800, Convert(nvarchar,'Vins et alcools Chevalier'), Convert(nvarchar,'59 rue de l''Abbaye'),
    Convert(nvarchar,'xxxxxx'), NULL, Convert(nvarchar,'51100'), Convert(nvarchar,'France'));

INSERT INTO [Orders2]
  ( [OrderID], [CustomerID], [EmployeeID], [OrderDate], [RequiredDate], [ShippedDate], [ShipVia],
    [Freight], [ShipName], [ShipAddress], [ShipCity], [ShipRegion], [ShipPostalCode], [ShipCountry] )
VALUES
  ( 10249, Convert(nvarchar,'TOMSP'), 6, '1996/07/05 00:00:00.000', '1996/08/16 00:00:00.000', '1996/07/10 00:00:00.000',
    1, 11.6100, Convert(nvarchar,'Toms Spezialitäten'), Convert(nvarchar,'Luisenstr. 48'),
 Convert(nvarchar,'Münster'), NULL,Convert(nvarchar,'44087'), Convert(nvarchar,'Germany'));

・・・

参考

性能測定情報

利用ガイド(ベターユース、FAQ編)

  • 4章:D層に関するトピック
    • 4.8.1項:SQLUtilityクラス
    • 4.8.2項:ExecGenerateSQLメソッド

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-08-07 (火) 17:34:30 (71d)