拡張メソッドを使ってトランザクション処理の見通しを良くしてみた

VB.netでは、意外とシンプルにトランザクション処理を実装することができるようになっていますが、CommandオブジェクトとTransactionオブジェクトが分離していて見通しが悪いなと感じたため、拡張メソッドにより使いやすくしてみました。

このようなケースでは、クラスを継承して機能を拡張するのが一般的ですが、OleDbCommandクラスは継承できない(NotInheritable Class)ことが分かり拡張メソッドを使うことになりました。

さて、実際に作成したモジュールが以下のものです。

Imports System.Runtime.CompilerServices
Imports System.Data.OleDb

''' <summary>
''' OleDbCommandクラスに4つの拡張メソッドを追加する
''' BeginTrans
''' CommitTrans
''' RollbackTrans
''' DisposeTrans
''' </summary>
''' <remarks></remarks>
Module modOledbCommandEx

    <Extension()>
    Public Sub BeginTrans(command As OleDbCommand)
        command.Transaction = command.Connection.BeginTransaction
    End Sub

    <Extension()>
    Public Sub CommitTrans(command As OleDbCommand)
        command.Transaction.Commit()
    End Sub

    <Extension()>
    Public Sub RollbackTrans(command As OleDbCommand)
        command.Transaction.Rollback()
    End Sub

    <Extension()>
    Public Sub DisposeTrans(command As OleDbCommand)
        If (command.Transaction IsNot Nothing) Then
            command.Transaction.Dispose()
        End If
    End Sub

End Module

 

 

拡張メソッドは標準モジュールに関数として定義します。ただし、Extension()属性を与えることだけが通常の関数との相違点です。

    <Extension()>

Extension属性は完全修飾名で書いてもいいですが、ここではImports句を使って名前空間を指定しています。

Imports System.Runtime.CompilerServices

このように拡張メソッドを定義することにより、OleDbCommandクラスには以下の4つのメソッドがあたかも最初から備わっていたかのように呼び出せるようになります。

  •  BeginTrans
  • CommitTrans
  • RollbackTrans
  • DisposeTrans

この4つの拡張メソッドを使うと、トランザクション処理は以下のように非常にシンプルで見通しの良いものになります。

        strConnectionString = "Provider=xxx;Data Source=xxx"
        conn = New OleDbConnection(strConnectionString)
        command = conn.CreateCommand()
        command.CommandText = "Update ..."
        command.BeginTrans()
        command.ExecuteNonQuery()
        command.CommitTrans()
        'or command.RollbackTrans()

 

WIth句を使うことでさらにシンプルになります。

        strConnectionString = "Provider=xxx;Data Source=xxx"
        conn = New OleDbConnection(strConnectionString)
        command = conn.CreateCommand()
        With command
            .CommandText = "Update ..."
            .BeginTrans()
            .ExecuteNonQuery()
            .CommitTrans()
            'or .RollbackTrans()
        End With