-
Notifications
You must be signed in to change notification settings - Fork 49
UserGuide_Developers.ja
2016年10月3日
- Open 棟梁を用いたアプリケーション開発を行う、SE・開発者
本ドキュメントは、開発者が把握しておくべき点について纏めています。開発者とは、(サブクラスなどに) それぞれの業務処理を実装するタスクを担う者を指します。
本ドキュメントに記載の会社名・商品名は、各社の商標または登録商標です。
本ドキュメントは、クリエイティブ・コモンズ CC BY 2.1 JP ライセンスの下で利用可能です。
図中の凡例:
- 赤枠:実装必須のコードブロック
- 赤枠 (破線):実装に注意が必要なコードブロック
- 青文字:任意の実装が可能なコードブロック
※ 各図の内容は、図の下にコードとして併記しています(図が表示されない場合もコードを参照できます)。
D・B 層を実装する前に、実装の際に必要となる「引数クラス」・「戻り値クラス」を作成します。
- 「引数クラス」・「戻り値クラス」は、必要に応じて作成する。
- クラス名称は任意の名称に変更可能である。
以下に実装のテンプレートを示します。サンプル プログラムに付属の「TestParameterValue」・「TestReturnValue」クラスの実装を参考にできます。
図 1-1 「引数クラス」の実装のテンプレート
using ProjectName.Infrastructure.Business.Common;
public class TestParameterValue : MyParameterValue // 「引数親クラス2」を継承する
{
// 「引数クラス」に必要な要素を追加定義する
public int ShipperID;
public string CompanyName;
public string Phone;
#region コンストラクタ
public TestParameterValue(string screenId, string controlId, string methodName, string actionType)
: base(screenId, controlId, methodName, actionType)
{
// Base のコンストラクタに引数を渡すために必要。
}
#endregion
}
図 1-2 「戻り値クラス」の実装のテンプレート
using ProjectName.Infrastructure.Business.Common;
public class TestReturnValue : MyReturnValue // 「戻り値親クラス2」を継承する
{
// 「戻り値クラス」に必要な要素を追加定義する
public object Obj;
public int ShipperID;
public string CompanyName;
public string Phone;
}「業務コード クラス」には、業務処理を実装します。
- 「業務コード クラス」は、必要に応じて作成する。
- 「MyFcBaseLogic」クラスを継承する。
- クラス名称は任意の名称に変更可能である。
以下に実装のテンプレートを示します(サンプルの「LayerB」クラスを参考にできます)。
図 2.1 「業務コード クラス」の実装のテンプレート
#region using
// System~
using System;
~
using ProjectName.Infrastructure.Business.Business;
#endregion
/// <summary>
/// LayerB の概要の説明です
/// </summary>
public class LayerB : MyFcBaseLogic // 「業務コード親クラス2」を継承する
{
}「業務コード クラス」に「業務処理」を実装する場合、「業務コード親クラス2」の「UOC_DoAction」メソッドに「業務処理メソッドの自動振り分け処理」が実装されているため、この振り分け処理に従い、「業務コード クラス」に UOC メソッドを追加して「業務処理」を実装します。
振り分け処理では、「引数親クラス1」のパラメタにある「methodName」プロパティを使用してメソッド名を生成し、レイトバインドにより処理を振り分けます。「振り分けロジック」のカスタマイズは自由ですが、デフォルトでは「UOC_(methodName に指定された文字列)」メソッドがレイトバインドにより呼び出されます。
図 2.2 「業務コード クラス」の「業務処理メソッド」の実装例
/// <summary>btnButton1 に対応する業務処理を実装</summary>
/// <param name="parameterValue">引数クラス</param>
private void UOC_(メソッド名)(XParameterValue xParameter)
{
// 戻り値クラスを生成
XReturnValue xReturn = new XReturnValue();
// 戻り値設定
this.ReturnValue = xReturn;
// ↓業務処理-----------------------------------------------------
// データアクセス クラスを生成する
LayerD myDao = new LayerD(this.GetDam());
myDao.xxxx(xParameter, xReturn);
// ↑業務処理-----------------------------------------------------
}- 引数クラスは、業務毎の型としてメソッド引数に定義できる (ベースクラスの型で定義する必要がない) ので、キャストは不要です。
- 「業務処理」の戻り値を戻す場合、
this.ReturnValueメンバ変数を使用して戻す必要があります (これにより、例外発生時にも戻り値が戻ります)。メソッドの先頭でメンバ変数にローカル変数の参照を設定しておくと良いでしょう。 - データアクセスのため「データアクセス クラス」を生成します (作成方法は次章を参照)。
- トランザクションをロールバックする場合は、「業務処理」内部で「業務例外」をスローします。「システム例外」をスローした場合、「その他、一般的な例外」が発生した場合もロールバックされます。それ以外の場合 (B 層が正常終了した場合) は、トランザクションは全てコミットされます。
「データアクセス クラス」には、業務のデータアクセス処理を実装します。
- 「データアクセス クラス」は、必要に応じて作成する。
- クラス名称は任意の名称に変更可能である。
以下に実装のテンプレートを示します(サンプルの「LayerD」クラスを参考にできます)。
図 3.1 「データアクセス クラス」の実装のテンプレート
#region using
// System~
using System;
~
using ProjectName.Infrastructure.Public.Util;
#endregion
/// <summary>
/// LayerD の概要の説明です
/// </summary>
public class LayerD : MyBaseDao // 「データアクセス親クラス2」を継承する
{
/// <summary>コンストラクタ</summary>
public LayerD(BaseDam dam) : base(dam)
{
// 基本的には何も実装しない
}
}B 層上で D 層を生成する場合、コンストラクタに「データアクセス制御クラス」を設定します。D 層は、この「データアクセス制御クラス」を保持し、データアクセスの際に使用します。
「データアクセス クラス」に「データアクセス処理」を実装する場合は、以下のテンプレートを利用してメソッドを実装します (メソッドのシグネチャは、下記のテンプレートに従った定義にする必要はありません)。
図 3.2 「データアクセス クラス」の「データアクセス処理」の実装例
#region テンプレ
public void テンプレ(TestParameterValue testParameter, TestReturnValue testReturn)
{
// ↓DBアクセス-----------------------------------------------------
// ● 下記のいづれかの方法で SQL を設定する。
// -- ファイルから読み込む場合。
this.SetSqlByFile2("ファイル名");
// -- 直接指定する場合。
this.SetSqlByCommand("SQL文");
// パラメタライズド・クエリのパラメタに対して、動的に値を設定する。
this.SetParameter("P1", testParameter.ShipperID);
// ● 下記のいづれかの方法で SQL を実行する。
object obj;
// -- 追加、更新、削除の場合(件数を確認できる)
obj = this.ExecInsUpDel_NonQuery();
// -- 先頭の1セル分の情報を返す SELECT クエリを実行する場合
obj = this.ExecSelectScalar();
// -- テーブル(or レコード)の情報を返す SELECT クエリを実行する場合(引数 = データテーブル)
obj = new DataTable();
this.ExecSelectFill_DT((DataTable)obj);
// -- テーブル(or レコード)の情報を返す SELECT クエリを実行する場合(引数 = データセット)
obj = new DataSet();
this.ExecSelectFill_DS((DataSet)obj);
// -- データリーダを返す
IDataReader idr = (IDataReader)this.ExecSelect_DR();
// ↑DBアクセス-----------------------------------------------------
// 戻り値を設定
testReturn.Obj = obj;
}
#endregion本フレームワークでは、SQL 文の指定方法を、以下の 2 つの方法から選択できます。
- ファイルから読み込む方法
- プログラム中のリテラル (文字列定数) を使用して直接指定する方法
SQL の指定方法によって、使用する API を使い分けます。
-
ファイルから読み込む場合:
GetConfigParameter.GetConfigValueメソッドで SQL ファイルの保存フォルダを取得し、Path.Combineで SQL ファイル名を連結して、SetSqlByFileメソッドのパス引数として渡します。最新版ではSetSqlByFile2メソッドの利用を推奨します (内部で sqlTextFilePath パラメタとの連結、埋め込みリソースからの読み込みをサポート)。
図 3.3.1-1 SQL をファイルから読み込む場合
// -- ファイルから読み込む場合。
this.SetSqlByFile(
Path.Combine(GetConfigParameter.GetConfigValue("sqlTextFilePath"), "ファイル名"));
// -- ファイル、埋め込まれたリソースから読み込む場合。
// 埋め込まれたリソースから読み込む場合、次の設定が必要になる。
// MyBaseDao.UseEmbeddedResource = true;
this.SetSqlByFile2("ファイル名");-
直接指定する場合:
SetSqlByCommandメソッドの SQL 引数に SQL 文の文字列リテラルを指定します。
図 3.3.1-2 SQL を直接指定する場合
// -- 直接指定する場合。
this.SetSqlByCommand("SQL文");SQL にユーザ定義パラメタを定義し、API を使用してプログラムから置換できます。以下、動的に SQL を生成する例を示します。
-
SQL にユーザ定義パラメタを定義する (ユーザ定義パラメタは
%で囲む)。SELECT c1, c2, c3 FROM t1 %Where% ORDER BY %COLUMN% %SEQUENCE%
-
SetSqlByCommandメソッド、またはSetSqlByFile(SetSqlByFile2)メソッドを使用して SQL を指定する。 -
SetUserParameterメソッドを使用して、ユーザ定義パラメタを置換する。// ユーザ定義パラメタを置換する(%% は指定しない)。 this.SetUserParameter("SEQUENCE", "DESC"); // %Where% →(置換)→ WHERE c4 = @p_c4, c5 = @p_c5 // %COLUMN% →(置換)→ c2 // %SEQUENCE% →(置換)→ DESC
図 3.3.2 ユーザ定義パラメタを置換する場合
-
完成した動的 SQL (パラメタライズド・クエリ)。
SELECT c1, c2, c3 FROM t1 WHERE c4 = @p_c4, c5 = @p_c5 ORDER BY c2 DESC
-
このパラメタライズド・クエリのパラメタを設定して SQL を実行する (次項で説明)。
※ ユーザ定義パラメタは、SQL インジェクション対策がされないため、置換用文字列変数のチェックをプログラム側で行うか、ユーザ入力を直接、置換用文字列変数として指定しないようにします。基本的に、ユーザ入力はパラメタライズド・クエリのパラメタとして指定します。
SQL は、SQL インジェクション対策や、条件検索などの動的 SQL におけるクエリ プランの再利用などの観点から、パラメタライズド・クエリを使用するのがデファクト スタンダードです。パラメタライズド・クエリの定義方法は DBMS 毎に異なるので注意します。
- SQL Server ではパラメタを「@ +パラメタ名」で定義する。
- Oracle ではパラメタを「: +パラメタ名」で定義する。
表 3.3.3 SQL Server と Oracle のパラメタライズド・クエリの例
| 項番 | 区分 | SQL Server の例 | Oracle の例 |
|---|---|---|---|
| 1 | INSERT | INSERT INTO Shippers (CompanyName, Phone) VALUES (@P2, @P3) |
INSERT INTO Shippers (CompanyName, Phone) VALUES (:P2, :P3) |
| 2 | UPDATE | UPDATE Shippers SET CompanyName = @P2, Phone = @P3 WHERE ShipperID = @P1 |
UPDATE Shippers SET CompanyName = :P2, Phone = :P3 WHERE ShipperID = :P1 |
| 3 | DELETE | DELETE Shippers WHERE ShipperID = @P1 |
DELETE Shippers WHERE ShipperID = :P1 |
| 4 | SELECT | SELECT ShipperID, CompanyName, Phone FROM Shippers WHERE ShipperID = @P1 |
SELECT ShipperID, CompanyName, Phone FROM Shippers WHERE ShipperID = :P1 |
パラメタライズド・クエリのパラメタに対して値を設定するには、SetParameter メソッドを使用します。オーバーロードしたメソッドでは、各データプロバイダのデータ型 .etc の指定も可能です。
図 3.3.4 パラメタライズド・クエリのパラメタ指定メソッド
// パラメタライズド・クエリのパラメタに対して、動的に値を設定する。
this.SetParameter("P1", testParameter.ShipperID);SQL の実行には、以下の 5 つのメソッドを利用できます。
図 3.3.5 SQL の実行に使用する 5 つのメソッド
// -- 追加、更新、削除の場合(件数を確認できる)
obj = this.ExecInsUpDel_NonQuery();
// -- 1セル分の情報を返す SELECT クエリを実行する場合
obj = this.ExecSelectScalar();
// -- テーブル(or レコード)の情報を返す SELECT クエリ(引数 = データテーブル)
obj = new DataTable();
this.ExecSelectFill_DT((DataTable)obj);
// -- テーブル(or レコード)の情報を返す SELECT クエリ(引数 = データセット)
obj = new DataSet();
this.ExecSelectFill_DS((DataSet)obj);
// -- データリーダを返す
IDataReader idr = (IDataReader)this.ExecSelect_DR();表 3.3.5 各メソッドと、実行する SQL・戻り値の関係
| 項番 | 区分 | 利用可能なメソッド | 戻り値 |
|---|---|---|---|
| 1 | INSERT | ExecInsUpDel_NonQuery() | 影響を受けた (追加された) 行の行数が返る。 |
| 2 | UPDATE | ExecInsUpDel_NonQuery() | 影響を受けた (更新された) 行の行数が返る。 |
| 3 | DELETE | ExecInsUpDel_NonQuery() | 影響を受けた (削除された) 行の行数が返る。 |
| 4 | SELECT | ExecSelectScalar() | 結果セットの、先頭の 1 セル分の情報が返る。 |
| 4 | SELECT | ExecSelectFill_DT() | 結果セット (データ テーブル型) が返る。※ データ テーブル型の引数を渡す。 |
| 4 | SELECT | ExecSelectFill_DS() | 結果セット (データ テーブル型) が返る。※ データ セット型の引数を渡す。 |
| 4 | SELECT | ExecSelect_DR() | データリーダが返る。 |
「コンテンツ ページ(画面コード クラス)」には、P 層のイベント処理を実装します。
- 「コンテンツ ページ(画面コード クラス)」は、必要に応じて作成する。
- クラス名称は任意の名称に変更可能である。
ソリューション エクスプローラ上の任意の位置で右クリックし [新しい項目の追加] を選択すると、[新しい項目の追加] ダイアログが表示されます。テンプレートから「Web フォーム」を選択し、[マスタ ページを選択する] チェック ボックスをオンにして、コンテンツ ページを作成します。
図 4.1.1-1 [新しい項目の追加] ダイアログ
すると [マスタ ページを選択してください] ダイアログが表示されるので、「コンテンツ ページ(画面コード クラス)」で使用する「マスタ ページ」を選択します。
図 4.1.1-2 [マスタ ページを選択してください] ダイアログ
上記の操作で、次の様なコンテンツ ページが作成されます。
図 4.1.1-3 作成されたコンテンツ ページ
<%@ Page Language="C#" MasterPageFile="~/Aspx/Common/TestScreen.master" AutoEventWireup="true"
CodeFile="testScreen.aspx.cs" Inherits="Aspx_testFxLayerP_testScreen" Title="Untitled Page" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
</asp:Content>※ 選択したマスタ ページの構成に合わせて、コンテンツ ページ上に ContentPlaceHolder が自動生成されます。ContentPlaceHolder 内の実装はユーザが自由に変更できます。
「コンテンツ ページ」の作成・デザインの完了後、コード ビハインドである「画面コード クラス」に処理を実装します。以下に実装のテンプレートを示します。
図 4.1.1-4 「画面コード クラス」の実装のテンプレート
// System~
using System;
~
using ProjectName.Infrastructure.Business.Util;
public partial class Aspx_testFxLayerP_testScreen : MyBaseController // 「画面コード親クラス2」を継承する
{
}「ページ ロード処理」は実装必須の処理です。「UOC_FormInit」、「UOC_FormInit_PostBack」メソッドを「画面コード クラス」でオーバーライドし、初回ロード時・ポストバック時を区別して実装できます。
図 4.1.2 「ページ ロード処理」の実装例
#region ページロードのUOCメソッド
/// <summary>ページロードのUOCメソッド(個別:初回ロード)</summary>
/// <remarks>実装必須</remarks>
protected override void UOC_FormInit()
{
// フォーム初期化(初回ロード)時に実行する処理を実装する
// TODO:
}
/// <summary>ページロードのUOCメソッド(個別:ポストバック)</summary>
/// <remarks>実装必須</remarks>
protected override void UOC_FormInit_PostBack()
{
// フォーム初期化(ポストバック)時に実行する処理を実装する
// TODO:
}
#endregion以下の手順に従います。
- 「マスタ ページ」上にコントロール ([prefix] 任意の文字列) を配置する。
- 「画面コード クラス」上に UOC メソッド
UOC_(マスタ ページ ファイル名)_[prefix]任意の文字列_Clickを実装する。
- 「マスタ ページ」上(ボタンのカスタム コントロールを選択した場合の例)
図 4.1.3-1 「マスタ ページ」の実装例
<cc1:WebCustomButton ID="btnMasterIdvdl" runat="server" Text="(ボタン表示名)" Width="220px" /><br />-
「画面コード クラス」上:イベント ハンドラのシグネチャは
protected string イベント ハンドラ名(FxEventArgs fxEventArgs)とします (GridView の RowUpdating/RowDeleting/PageIndexChanging/Sorting は(FxEventArgs fxEventArgs, EventArgs e))。マスタ ページ ファイル名=「TestScreen.master」の場合:
図 4.1.3-2 「画面コード クラス」の実装例
protected string UOC_TestScreen_btnMasterIdvdl_Click(FxEventArgs fxEventArgs)
{
// TODO:
// 画面遷移しないポストバックの場合は、url を空文字列に設定する
return "";
}イベント処理を実装する UOC メソッドは、共通イベントハンドラからレイトバインドで呼び出されるため、「public」か「protected」で定義する必要があります (aspx.cs(vb) の「private」は特殊でレイトバインド不可能)。URL をリターンする場合は画面遷移し、空文字列をリターンする場合は画面遷移せずポストバックになります。
以下の手順に従います。
- コンテンツ ページ上にコントロール ([prefix] 任意の文字列) を配置する。
- 「画面コード クラス」上に UOC メソッド
UOC_[prefix]任意の文字列_Clickを実装する。
- コンテンツ ページ上の実装例(ボタンのカスタム コントロールを選択した場合の例)
図 4.1.4-1 コンテンツ ページ上の実装例
<cc1:WebCustomButton ID="btnCntnt" runat="server" Text="(ボタン表示名)" Width="220px" /><br />- 「画面コード クラス」上の実装例:
図 4.1.4-2 「画面コード クラス」上の実装例
protected string UOC_btnCntnt_Click(FxEventArgs fxEventArgs)
{
// TODO:
// 画面遷移しないポストバックの場合は、url を空文字列に設定する
return "";
}「業務コード クラス」のメソッド呼び出し処理は、主として「コントロールのイベント処理」上に実装します。以下に呼び出し処理のサンプルを示します(サンプルの「画面コード クラス」を参考にできます)。
図 4.2 「業務コード クラス」のメソッド呼び出し処理
/// <summary>イベントハンドラ</summary>
/// <param name="fxEventArgs">イベントハンドラの共通引数</param>
/// <returns>URL</returns>
protected string UOC_(任意のイベントハンドラ名)(FxEventArgs fxEventArgs)
{
// 引数クラスを生成(引数値の設定)
TestParameterValue testParameterValue
= new TestParameterValue(
this.ContentPageFileNoEx, // 画面を表す文字列
fxEventArgs.ButtonID, // イベント発生元のコントロールID
"(任意のmethodName値)", // 呼び出す B層のメソッド名
"(任意のactionType値)", // 条件分岐などに使用するパラメタ
this.UserInfo); // ユーザ情報(ベース2で追加)
// 分離レベルの設定
DbEnum.IsolationLevelEnum iso = this.SelectIsolationLevel();
// B層を生成
LayerB myBusiness = new LayerB();
// 業務処理を実行
TestReturnValue testReturnValue =
(TestReturnValue)myBusiness.DoBusinessLogic(
(BaseParameterValue)testParameterValue, iso);
// 結果表示するメッセージ エリア
Label label = (Label)this.GetMasterWebControl("Label1");
label.Text = "";
if (testReturnValue.ErrorFlag == true)
{
// 結果(業務続行可能なエラー)
label.Text = "ErrorMessageID:" + testReturnValue.ErrorMessageID + "\n";
label.Text += "ErrorMessage:" + testReturnValue.ErrorMessage + "\n";
label.Text += "ErrorInfo:" + testReturnValue.ErrorInfo + "\n";
}
else
{
// 結果(正常系)
label.Text = testReturnValue.Obj.ToString();
}
// 画面遷移しないポストバックの場合は、url を空文字列に設定する
return "";
}-以上-