.NETエンタープライズ
Webアプリケーション開発技術大全

接続型データアクセスと短時間トランザクション

マイクロソフト コンサルティング本部 赤間 信幸
2005/03/15


3.2 データベーストランザクション

 データベーストランザクションとは、図3-4のようにデータベース上にストアドプロシージャを配置し、これを.NETアプリケーションから「かたまり」として呼び出して利用する方法である。

図3-4 データベーストランザクション

3.2.1 実装方法

 データベーストランザクションを実装するために行うべき作業は、ストアドプロシージャの作成と、.NETアプリケーションからの呼び出しである。

A. ストアドプロシージャの作成

 クエリアナライザからCREATE PROCEDURE命令を利用するか、あるいはSQL EnterpriseManager上からストアドプロシージャの定義を行うことで作成できる。ここでは、第2章の変換デッドロックの解説で採り上げたサンプルコード(リスト2-11)をストアドプロシージャ化してみよう※3

※3 「第7章 サービスコンポーネントを用いたアプリケーション設計時の注意点」で詳しく取り扱うため、ここでは深入りしないが、リスト3-1のSELECT直後の分岐ルートは、ROLLBACK TRANSACTIONではなくCOMMIT TRANSACTIONでも構わないことに注意しよう。この分岐は指定されたtitle_idが存在せず、UPDATEに失敗した場合のルートであるが、データの更新は行っていない。このため書き込みを取り消す必要がないので、COMMIT TRANSACTIONとしても構わない。トランザクションのロールバックと、ストアドプロシージャの戻り値やエラー発生有無とは独立しているため、トランザクションをコミットしつつエラーを発生させる、といったことも可能である。
 
Transact-SQL

USE pubs
GO

CREATE PROCEDURE RaisingPrice
   @title_idvarchar(6)
AS

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
DECLARE @val MONEY

BEGIN TRANSACTION

SELECT @val = price FROM titles WITH (UPDLOCK) WHERE title_id = @title_id
IF @val IS NULL
   BEGIN
   ROLLBACK TRANSACTION
   RETURN 1
   END

SET @val = @val + 1
UPDATE titles SET price = @val WHERE title_id = @title_id

COMMIT TRANSACTION

RETURN 0
リスト3-1 ストアドプロシージャの作成(クエリアナライザから実施する場合)

B. .NETアプリケーションからの呼び出し

 データベース上に作成されたストアドプロシージャは、.NETアプリケーションからSqlCommandオブジェクトを用いて呼び出すことができる。そのサンプルコードをリスト3-2に示す※4

※4 なお、一般にストアドプロシージャの開発ではストアドプロシージャ呼び出しの準備作業が面倒である。しかし、Visual Studio .NETのサーバエクスプローラとデザイン画面を利用すれば、ドラッグ&ドロップのみでストアドプロシージャ呼び出し用のSqlCommandオブジェクトを簡単に準備できる。この場合、リスト3-2のストアドプロシージャの呼び出しは以下のようなコードのみで済む。
C#の場合

sqlCommand1.Parameters["@title_id"].Value = "PS2106";
try
{
    sqlConnection1.Open();
    sqlCommand1.ExecuteNonQuery();
    Console.WriteLine(sqlCommand1.Parameters["@RETURN_VALUE"].Value);
}
catch
{
    sqlConnection1.Close();
}
 
C#の場合

SqlConnection sqlcon = new SqlConnection("server=localhost;database=pubs;user
id=sa;password=p&ssw0rd;");
SqlCommand sqlcmd = new SqlCommand("RaisingPrice", sqlcon);
SqlParameter sqlpr = new SqlParameter("@RETURN_VALUE", SqlDbType.Int);
sqlpr.Direction = ParameterDirection.ReturnValue;
sqlcmd.Parameters.Add(sqlpr);
sqlcmd.CommandType = System.Data.CommandType.StoredProcedure;
sqlcmd.Parameters.Add("@title_id", "PS2106");

try
{
   sqlcon.Open();
   sqlcmd.ExecuteNonQuery();
   int result = (int)sqlpr.Value;
   Console.WriteLine(result);
}
finally
{
   sqlcon.Close();
}
VB.NETの場合

Dim sqlcon As SqlConnection = New SqlConnection("server=localhost;database=pubs;user
id=sa;password=p&ssw0rd;")
Dim sqlcmd As SqlCommand = New SqlCommand("RaisingPrice", sqlcon)

Dim sqlpr As SqlParameter = New SqlParameter("@RETURN_VALUE", SqlDbType.Int)
sqlpr.Direction = ParameterDirection.ReturnValue
sqlcmd.Parameters.Add(sqlpr)
sqlcmd.CommandType = System.Data.CommandType.StoredProcedure
sqlcmd.Parameters.Add("@title_id", "PS2106")

Try
    sqlcon.Open()
    sqlcmd.ExecuteNonQuery()
    Dim result As Integer = CType(sqlpr.Value, Integer)
    Console.WriteLine(result)
Finally
    sqlcon.Close()
End Try
リスト3-2 .NETアプリケーションからのストアドプロシージャの呼び出しC#の場合

3.2.2 メリットとデメリット

 このデータベーストランザクション制御方式の主なメリットとデメリットは以下の通りである。

A. 主なメリット

 この方式は、データベース内に閉じた形で一連の処理が進むので、パフォーマンスが良いというメリットがある。

B. 主なデメリット

 データベーストランザクションを利用する場合、現在のSQL Server 2000ではTransact-SQLと呼ばれるSQL Serverのネイティブ言語での開発が必要になる。しかし、Transact-SQLは細かいビジネスロジックの記述には不向きな言語であり、またC#などの一般的なアプリケーション開発者からすると多少敷居の高いものである。このため、十分な実装スキルを持つ開発者の確保が容易ではないという問題がある。

 この点に関しては、次期バージョンのSQL Server 2005(コードネームYukon)にて改善される予定であり、これを用いるとストアドプロシージャをC#やVB .NETで開発することが可能になる。しかしこの場合でも、業務処理が中間層とデータベース層とに分散してしまうため、適切な役割分担に基づいた設計が難しいという問題が残る。

 またストアドプロシージャに関しては、.NETのアセンブリファイルのような標準的なバージョン管理手法が提供されておらず、定式化されたアプリケーション入れ替え手法なども存在しない。このため頻繁にストアドプロシージャが変更されるような場合には、その管理が厄介になる。

 以上のような理由から、ストアドプロシージャとそれを用いた短時間トランザクション制御は、特にパフォーマンスが求められる部分にのみ限定的に利用されることが多い※5

※5 一般的に、ストアドプロシージャはバッチ処理との相性がよい。これは以下のような理由による。バッチ処理は、データベース上の1レコード単位に処理を行うことが多い。これをマニュアルトランザクションなどで記述するとデータベースとのラウンドトリップ回数が増えてしまうが、ストアドプロシージャを利用すると、ラウンドトリップの過多による性能劣化を防ぐことができる。この観点から、バッチ処理の開発においてはストアドプロシージャの利用は有力な選択肢の1つとなる。しかし、オンラインバッチなどバッチ処理の中でトランザクション制御が必要となる場合には、ミニバッチ化やサーバカーソルの適切な利用などが求められるようになり、単にストアドプロシージャを使えば済むという話ではなくなる。これについては本書「第9章 複雑なトランザクション制御」の「9.3 オンライン型長時間バッチ処理」の項にて解説しているので、参考にして頂きたい。
 

 INDEX
  .NETエンタープライズWebアプリケーション 開発技術大全
  接続型データアクセスと短時間トランザクション
    1.業務的なトランザクション制御
  2.データベーストランザクション
    3.マニュアルトランザクション
    4.自動トランザクション
    5.短時間トランザクション処理の3つの制御方式の比較
 
インデックス・ページヘ  「.NETエンタープライズWebアプリケーション開発技術大全」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間