「[[Open棟梁 wiki>https://opentouryo.osscons.jp]]」は、「[[Open棟梁Project>https://github.com/OpenTouryoProject/]]」,「[[OSSコンソーシアム .NET開発基盤部会>https://www.osscons.jp/dotNetDevelopmentInfrastructure/]]」によって運営されています。 -戻る --[[モジュール構成]] --[[データアクセス]] *目次 [#n987a637] #contents *概要 [#xd0bad3f] *詳細 [#ya27e458] **自作Daoクラス [#p684509d] ***ユース・ケース [#n0c1e1e6] 個別にDaoクラスを使用してデータ アクセスする場合、~ インテリジェンスなD層(Dao)クラス として、機能毎に「自作Daoクラス」を実装。 ***サンプル・コード [#e5b6269d] -[[性能を考慮した動的パラメタライズド・クエリの連続実行方法>バッチ処理方式#y92d7822]] -ストアド プロシージャの実行~ 最新版では、SetParameterの拡張により、[[汎用Daoクラス>#w11892a0]]でも実行可能になった。 /// <summary>「sp_help」ストアドプロシージャを実行する。</summary> /// <param name="objectName">「sp_help」ストアドプロシージャの「objname」パラメタに指定する文字列</param> /// <param name="ds">「sp_help」ストアドプロシージャが返す結果セット(複数返る)</param> /// <returns>「sp_help」ストアドプロシージャの戻り値(成功:「」、失敗:「」)</returns> public int sp_help(string objectName, out DataSet ds) { // ストアドプロシージャを指定する。 this.SetSqlByCommand("sp_help", CommandType.StoredProcedure); // CommandTypeにStoredProcedureを設定 // 引数パラメタを設定する。 this.SetParameter("objname", objectName); // 戻り値パラメタを設定する。 // 戻り値用のパラメタを指定する場合、Parameter.Directionプロパティに、ParameterDirection.ReturnValueを指定する。 // アウトプット パラメタを指定する場合も、同様に、Parameter.Directionプロパティに、ParameterDirection.Outputを指定する。 this.SetParameter("ret", null, null, -1, ParameterDirection.ReturnValue); // ストアドプロシージャを実行し、データリーダを戻す。 // ストアド プロシージャの実行には、this.ExecSelect_DR()メソッドを使用する。 SqlDataReader drd = (SqlDataReader)this.ExecSelect_DR(); // 結果セットを取得する ds = new DataSet(); // 結果セットは複数取得可能 // ループなどを使用して複数の結果セットを取得できる。 // DataTable.Load()メソッドでは、結果セットが自動的に次に送られる。 // DataTable.Load()メソッドを使用しない場合、DataReader.NextResult()メソッドを使用して、次に読む結果セットに進む。 do { // DataTableを生成 DataTable dt = new DataTable(); // データリーダから結果をロード dt.Load(drd); // DataTableを格納 ds.Tables.Add(dt); } while (!drd.IsClosed); // データリーダを閉じる。 drd.Close(); // ストアドプロシージャの戻り値パラメタの値を取得。 return (int)this.GetDam.GetParameter("ret").Value; } **汎用Daoクラス(CmnDao) [#f357a5ed] ***ユース・ケース [#r48796a8] 汎用的なDaoクラスを使用して主に参照系のデータアクセス処理を実行する。 ***ソース・コード [#q447bb81] https://github.com/OpenTouryoProject/OpenTouryo/blob/develop/root/programs/CS/Frameworks/Infrastructure/Business/Dao/CmnDao.cs ***サンプル・コード [#w11892a0] -最も簡単なデータアクセス例 // 汎用Daoで参照系SQLを実行 CmnDao cmnDao = new CmnDao(this.GetDam()); // 動的SQLを指定 cmnDao.SQLFileName = "ShipperSelect.xml"; // パラメタ ライズド クエリのパラメタに対して、動的に値を設定する。 cmnDao.SetParameter("P1", testParameter.ShipperID); // 戻り値 dt DataTable dt = new DataTable(); // 汎用Daoを実行 cmnDao.ExecSelectFill_DT(dt); -パラメタライズド・クエリを使用した条件検索 + あいまい検索処理~ 動的SQLには、動的パラメタライズド・クエリが有効である。~ 条件検索 + あいまい検索という複雑なSQLであっても、~ 以下のようなSQL定義(XML)とプログラムで容易に対応が可能である。 --SQL定義 <?xml version="1.0" encoding="shift_jis" ?> <ROOT> SELECT A, B, C FROM T WHERE <IF>AND A = @A</IF> <IF name="A_LIKE">AND A LIKE @LIKE_A</IF> <IF>AND B = @B</IF> <IF name="B_LIKE">AND B LIKE @LIKE_B</IF> <IF>AND C = @C</IF> ORDER BY <IF name="SEQUENCE">A<ELSE>B</ELSE></IF> </ROOT> --コード ' ファイルから読み込む Me.SetSqlByFile2("XXX.xml") ' パラメタ設定 ' パラメータA If PV.A <> "" Then If PV.A_IsAimai Then ' LIKE前方一致検索 Me.SetParameter("LIKE_A", PV.A & "%") Else ' 通常の=一致検索 Me.SetParameter("A", PV.A) End If End If ' パラメータB If PV.B <> "" Then If PV.B_IsAimai Then ' LIKE前方一致検索 Me.SetParameter("LIKE_B", PV.B & "%") Else ' 通常の=一致検索 Me.SetParameter("B", PV.B) End If End If ' パラメータC Me.SetParameter("C", PV.C) ' 並び順 Me.SetParameter("SEQUENCE ", PV.SEQ) ' 結果セットの取得 RV.dt = New DataTable() Me.ExecSelectFill_DT(RV.dt) ※ LIKE句で使用する、「 % 」や「 _ 」などのワイルドカードを~ 文字列中で使用する場合は、これも別途エスケープする必要がある。 -ストアドプロシージャの利用例 --その1 // 汎用Daoでストアドを実行 CmnDao cmnDaoSP = new CmnDao(this.GetDam()); // ストアドを指定 cmnDaoSP.SQLText = "sp_help"; // パラメタを指定する(入力、出力)。 cmnDaoSP.SetParameter("objname", "Shippers"); cmnDaoSP.SetParameter("ret", null, null, -1, ParameterDirection.ReturnValue); // 汎用Daoを実行 SqlDataReader drd = (SqlDataReader)cmnDaoSP.ExecSelect_DR(); // 結果セットを取得する DataSet ds = new DataSet(); // 結果セットは複数取得可能 do { // DataTableを生成 DataTable dt = new DataTable(); // データリーダから結果をロード dt.Load(drd); // DataTableを格納 ds.Tables.Add(dt); } while (!drd.IsClosed); // データリーダを閉じる。 drd.Close(); // 戻り値を取得 int i = (int)cmnDaoSP.GetParameter("ret"); --その2 ---Open棟梁の汎用Daoを使用したストアド実行サンプル~ https://gist.github.com/daisukenishino2/a97e2017a0c683d2c858e39741b63949 ***ソース・コード [#q447bb81] これだけ、部品なので、以下にソース・コードがある。 https://github.com/OpenTouryoProject/OpenTouryo/blob/develop/root/programs/CS/Frameworks/Infrastructure/Business/Dao/CmnDao.cs **自動生成Daoクラス [#t389966a] ***ユース・ケース [#p35ad416] 自動生成したDaoクラスを使用してデータ アクセスする場合、 -[[D層自動生成ツール]]を使用すれば、テーブル単位のCRUD部品を自動生成可能。 -更新系処理は、この「自動生成Daoクラス」を使用してデータ アクセスする。 ***サンプル・コード [#vcc99a63] -参照~ https://github.com/OpenTouryoProject/OpenTouryo/blob/develop/root/programs/CS/Samples/2CS_sample/GenDaoAndBatUpd_sample/Business/LayerB_BatUpd.cs#L143 // 戻り値クラスを生成 TestReturnValue testReturn = new TestReturnValue(); // ↓業務処理----------------------------------------------------- // データアクセス クラスを生成する DaoProducts daoProducts = new DaoProducts(this.GetDam()); // 全件取得 DataTable dt = new DataTable(); daoProducts.D2_Select(dt); // 戻り値を戻す testReturn.dt = dt; -(バッチ)更新~ https://github.com/OpenTouryoProject/OpenTouryo/blob/develop/root/programs/CS/Samples/2CS_sample/GenDaoAndBatUpd_sample/Business/LayerB_BatUpd.cs#L34 // 戻り値クラスを生成 TestReturnValue testReturn = new TestReturnValue(); // ↓業務処理----------------------------------------------------- // データアクセス クラスを生成する DaoProducts daoProducts = new DaoProducts(this.GetDam()); // ROW毎に処理 foreach (DataRow dr in testParameter.dt.Rows) { // パラメタをクリアする。 daoProducts.ClearParametersFromHt(); switch (dr.RowState) { case DataRowState.Added: #region 1件挿入 // 設定(インサート値) daoProducts.PK_ProductID = dr["ProductID"].ToString(); daoProducts.ProductName = dr["ProductName"].ToString(); daoProducts.SupplierID = dr["SupplierID"].ToString(); daoProducts.CategoryID = dr["CategoryID"].ToString(); daoProducts.QuantityPerUnit = dr["QuantityPerUnit"].ToString(); daoProducts.UnitPrice = dr["UnitPrice"].ToString(); daoProducts.UnitsInStock = dr["UnitsInStock"].ToString(); daoProducts.UnitsOnOrder = dr["UnitsOnOrder"].ToString(); daoProducts.ReorderLevel = dr["ReorderLevel"].ToString(); daoProducts.Discontinued = dr["Discontinued"].ToString(); // インサート(S1でよい) testReturn.obj = daoProducts.S1_Insert(); #endregion break; case DataRowState.Deleted: #region 1件削除 // 設定(主キー) daoProducts.PK_ProductID = dr["ProductID", DataRowVersion.Original].ToString(); // ★ 楽観排他をする場合は、ここにタイムスタンプを追加する。 // デリート(タイムスタンプを指定する場合は、D4_Delete) testReturn.obj = daoProducts.D4_Delete(); #endregion break; case DataRowState.Modified: #region 1件更新 // 設定(主キー) daoProducts.PK_ProductID = dr["ProductID"].ToString(); // ★ 楽観排他をする場合は、ここにタイムスタンプを追加する。 // ↓は、DataRowVersion.Originalを使用した楽観排他の例 daoProducts.ProductName = dr["ProductName", DataRowVersion.Original].ToString(); daoProducts.SupplierID = dr["SupplierID", DataRowVersion.Original].ToString(); daoProducts.CategoryID = dr["CategoryID", DataRowVersion.Original].ToString(); daoProducts.QuantityPerUnit = dr["QuantityPerUnit", DataRowVersion.Original].ToString(); daoProducts.UnitPrice = dr["UnitPrice", DataRowVersion.Original].ToString(); daoProducts.UnitsInStock = dr["UnitsInStock", DataRowVersion.Original].ToString(); daoProducts.UnitsOnOrder = dr["UnitsOnOrder", DataRowVersion.Original].ToString(); daoProducts.ReorderLevel = dr["ReorderLevel", DataRowVersion.Original].ToString(); daoProducts.Discontinued = dr["Discontinued", DataRowVersion.Original].ToString(); // 更新値設定 daoProducts.Set_ProductName_forUPD = dr["ProductName"].ToString(); daoProducts.Set_SupplierID_forUPD = dr["SupplierID"].ToString(); daoProducts.Set_CategoryID_forUPD = dr["CategoryID"].ToString(); daoProducts.Set_QuantityPerUnit_forUPD = dr["QuantityPerUnit"].ToString(); daoProducts.Set_UnitPrice_forUPD = dr["UnitPrice"].ToString(); daoProducts.Set_UnitsInStock_forUPD = dr["UnitsInStock"].ToString(); daoProducts.Set_UnitsOnOrder_forUPD = dr["UnitsOnOrder"].ToString(); daoProducts.Set_ReorderLevel_forUPD = dr["ReorderLevel"].ToString(); daoProducts.Set_Discontinued_forUPD = dr["Discontinued"].ToString(); // アップデート(タイムスタンプを指定する場合は、D3_Update) testReturn.obj = daoProducts.D3_Update(); #endregion break; default: break; } } **Dao集約クラス [#ra46728e] ***ユース・ケース [#af2d7044] 汎用的なDaoクラス、自動生成したDaoクラスを集約する場合、 -B層から「汎用Daoクラス」、「自動生成Daoクラス」を集約して使用することも可能。 -このクラスを「Dao集約クラス」と呼ぶ。 ***サンプル・コード [#r490f51a] /// <summary>Dao集約クラスのベースクラスの例</summary> public class BaseConsolidateDao { /// <summary>データアクセス制御クラス</summary> private BaseDam _dam; /// <summary>データアクセス制御クラス</summary> protected BaseDam Dam { get { return this._dam; } } /// <summary>コンストラクタ</summary> /// <param name="dam">データアクセス制御クラス</param> public BaseConsolidateDao(BaseDam dam) { this._dam = dam; } } *メソッド [#sa6028f2] 以下のメソッドを使用してデータアクセスを行う。 **SQL設定処理 [#d201de8d] -SetSqlByFileメソッド -SetSqlByCommandメソッド **コネクション & トランザクション管理 [#ma366933] -ConnectionOpenメソッド -ConnectionCloseメソッド -BeginTransactionメソッド -CommitTransactionメソッド -RollbackTransactionメソッド **SQLパラメタ設定処理 [#d67f7231] -SetUserParameterメソッド -SetParameterメソッド -GetParameterメソッド -ClearParametersメソッド **クエリの実行 [#hae319c9] -ExecSelectScalarメソッド -ExecSelectFill_DTメソッド -ExecSelectFill_DSメソッド -ExecSelect_DRメソッド -ExecInsUpDel_NonQueryメソッド IP:202.246.252.97 TIME:"2020-04-01 (水) 16:10:32" REFERER:"https://opentouryo.osscons.jp/index.php?cmd=edit&page=D%E5%B1%A4%EF%BC%88Dao%EF%BC%89%E3%81%AE%E7%A8%AE%E9%A1%9E" USER_AGENT:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"