データの整合性を確保するためのトランザクション制御
実例で学ぶASP.NET Webフォーム業務アプリケーション開発のポイント 第5回
ダウンロード サンプルファイル (5.6 MB)
トランザクション制御を行う際のポイント
トランザクション制御の実装方法まで分かったところで、実際にトランザクション制御を行う際のポイントをいくつか紹介します。
ポイント1:トランザクション制御はビジネスロジック層で行う
トランザクション制御は、プレゼンテーション層でもデータアクセス層でもなく、ビジネスロジック層で行うようにします。リスト2で掲載したコードもビジネスロジック層のものです。
これは、トランザクション制御の方針がビジネスロジックの要件に左右されるためです。
仮にデータアクセス層でトランザクション制御を行ってしまうと、複数のテーブルに対しての処理を1つのトランザクションにまとめることができなくなってしまいます。また、1つのトランザクションにしようと1つのデータアクセス層処理で複数のテーブルを更新してしまっては、それはすでにデータアクセスではなくビジネスロジックの役割を与えられていることになるので、これはその処理をビジネスロジック層に移動させるべきです。
ポイント2:可能ならビジネスロジック層の処理の全体をトランザクション制御対象とする
ビジネスロジック層に更新処理メソッドがあった場合、更新処理メソッドの最初でトランザクションを開始し、最後にトランザクションをコミット/ロールバックするようにすべきです。
/// <summary>
/// 予約情報を更新します。
/// </summary>
/// <param name="reservation"></param>
public void Update(Reservation reservation)
{
using (var ts = new TransactionScope())
{
if (OverlapsOtherReservation(reservation))
{
// 重複した予約あり
throw new OverlapReservationException();
}
_reservationRepository.Update(reservation);
_reservationRepository.Save();
ts.Complete();
}
}
これは次のように、中途半端にトランザクションの範囲を絞ることで、トランザクションに参加しないデータアクセスが発生することを防ぐためです。そのデータアクセスが参照系だけならそれほど影響はありませんが、更新系処理をうっかりトランザクションに参加させなかった場合、本記事冒頭の「トランザクション制御なし」と同じように、その更新処理だけ独立して確定されてしまいます。
public void Update(Reservation reservation)
{
if (OverlapsOtherReservation(reservation))
{
// 重複した予約あり
throw new OverlapReservationException();
}
using (var ts = new TransactionScope())
{
_reservationRepository.Update(reservation);
_reservationRepository.Save();
ts.Complete();
}
}
なお、ビジネスロジックの要件として複数のトランザクションを制御しなければならないような場合はこの限りではありません。ただ、可能な限りトランザクションのスコープは広くとるべきです。そのためにも、次のようにトランザクションの単位でメソッドアウトすることをお勧めします。
public void UpdateTables(ComplexData data) // (1)
{
UpdateTable1(data.Table1Entity);
UpdateTable2(data.Table2Entity);
}
private void UpdateTable1(Table1Entity entity) // (2)
{
using (var ts = new TransactionScope())
{
// Table1更新処理
ts.Complete();
}
}
private void UpdateTable2(Table2Entity entity)
{
using (var ts = new TransactionScope())
{
// Table2更新処理
ts.Complete();
}
}
(1)更新処理メインロジックのメソッドでは、各トランザクション管理対象毎のメソッドを呼ぶようにする。
(2)トランザクション制御対象処理ごとにprivateなメソッドとしてメソッドアウトする。このメソッドでは内部の処理すべてをTransactionScopeのusingブロックで囲みます。
まとめ
データの整合性を保つためのトランザクション制御のポイントは、以下のとおりです。
- データを更新する際の一連の処理の塊を「トランザクション」という。
- トランザクション制御とは、一連の処理の開始、確定(コミット)、取消(ロールバック)を制御することをいう。
-
トランザクション制御には大きく分けて2つのタイプがある。
-
明示的トランザクション制御
バッチ処理などでよく使われる。分散トランザクションには対応していない。
自分でトランザクションの開始、確定、取消をすべて制御する方法。 -
暗黙的トランザクション制御
現在の主流のトランザクション制御方法。
分散トランザクションに対応している上、構文がシンプルになる。
-
明示的トランザクション制御
-
トランザクション制御の実装は次のように行う。
-
明示的トランザクション制御
IDbConnection.BeginTransactionメソッドでトランザクションを開始し、IDbTransaction.Commit/Rollbackメソッドで終了させる。 -
暗黙的トランザクション制御
System.Transaction.TransactionScope型をusingブロックともに使用し、コミットしてよい場合、usingブロックの最後でTransactionScope.Completeメソッドを呼び出す。
-
明示的トランザクション制御
-
トランザクション制御のポイントは次の2つ。
- ポイント1:トランザクション制御はビジネスロジック層で行う。
- ポイント2:トランザクション制御対象処理ごとにメソッドを作成し、極力メソッドの内部すべてを1つのトランザクション制御範囲とする。
さて、次回はデータの整合性を保つために必要なもう一つの要素、排他制御について紹介する予定です。次回もお楽しみに。
この記事は参考になりましたか?
既に会員の方はを行ってください。
- 実例で学ぶASP.NET Webフォーム業務アプリケーション開発のポイント連載記事一覧
- この記事の著者
-
山田 祥寛(ヤマダ ヨシヒロ)
静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数。
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
-
WINGSプロジェクト 高野 将(タカノ ショウ)
<個人紹介>新潟県長岡市在住の在宅リモートワークプログラマー。家事や育児、仕事の合間に長岡IT開発者勉強会(NDS)、Niigata.NET、TDDBCなどのコミュニティに関わったり、Web記事や書籍などの執筆を行ったりしている。著書に『アプリを作ろう! Visual C#入門 Visual C# 2017対応』(日経BP社、2017)など。< WINGSプロジェクト について>有限会社 WINGSプロジェクト が運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での 登録メンバ は約50名で、現在も執筆メンバを 募集中 。興味のある方は、どしどし応募頂きたい。 著書 、 記事 多数。 RSS X: @WingsPro_info (公式)、 @WingsPro_info/wings (メンバーリスト) Facebook
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
この記事は参考になりましたか?
この記事をシェア
