SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

japan.internet.com翻訳記事

Visual Studio .NETのウィザードを使ってN階層アプリケーションを作成する:パート3

Visual Studio 2005でビジネスロジック層を効率扱う方法

マクロを使ってデータアクセスコードを生成する

 データアクセス層のコードは、テーブル名が異なるだけで繰り返しが多いので、コードの自動生成に適しています。コードジェネレータにはさまざまな種類があり、それぞれに長所と短所があります。私は最近、マクロを使ってコードを生成する方法を調べています。この方法の長所は、IDEのコンテキストで生成が行われることです。すべての書式化、インデント、Endタグの挿入が、手動でコードを入力しているときと同じように行われます。

 マクロを作成するには、VSの上部メニューから[Tools]→[Macros]→[Macros IDE]を選択します。VSに似た別のIDEが開き、マクロを編集できます。クラスリストの[MyMacros]を右クリックし、GenDataAccessLayerという名前の新しいクラス(モジュール)を追加します。新しいクラスの内側に、以降で紹介するメソッドを作成します。

 このマクロでは、リフレクションを使ってデータセットを参照し、各テーブルアダプタをインスタンス化して、それぞれのFillメソッドを呼び出します。まず、次の名前空間をインクルードする必要があります。

Imports EnvDTE
Imports EnvDTE80
Imports System.Diagnostics
Imports System.Reflection
Imports System

 マクロ内では、Visual Studio統合開発環境(DTE)を通じて、アクティブ文書へのポインタを使用できます。このポインタは、ソリューションエクスプローラ内で現在開いているアイテムを指します。また、そのアイテムがどのプロジェクトに含まれているかも認識しています。

Public Sub DefineTAviaReflectionVB()
    Dim pItem As ProjectItem = DTE.ActiveDocument.ProjectItem
    Dim ItemName As String = _
        pItem.Name.Substring(0, pItem.Name.LastIndexOf("."))
    Dim proj As Project = pItem.ContainingProject
    Dim line As String = ""
    Dim TableName As String
    Dim taList As String
    Dim UpdateList As String = ""
    Dim UpdateType As MethodInfo

 完全プロジェクト名に基づいて、実際のアセンブリのパスを作成します。BusinessクラスライブラリではなくWindows Formsアセンブリを作成する場合は、.DLL拡張子ではなく、.EXE拡張子を使用します。

ProjName = ProjName.Substring(0, ProjName.LastIndexOf("\") + 1)
ProjName = ProjName & "bin\debug\" & proj.Name & ".dll"

 アセンブリが既にある場合は、このパスからアセンブリをロードできます。プロジェクト自体からアセンブリへの参照を取得するもっとよい方法があるのかもしれませんが、今のところ私はこの方法しか知りません。

Dim targetAssembly As Assembly = Assembly.LoadFrom(ProjName)

 アセンブリ内の個々の型をループ処理し、データセットテーブルアダプタのグループの中から末尾が「TableAdapter」のものを探します。

For Each typ As Type In targetAssembly.GetTypes()
    If typ.FullName Like "*" & ItemName & "TableAdapters." & _
             "*TableAdapter" Then
        TableName = typ.Name.Substring(0, _
            typ.Name.LastIndexOf("TableAdapter"))

 実際にコードを生成する部分は次の通りです。

line = "Dim ta" & TableName & " As " & ItemName & _
"TableAdapters." & typ.Name
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text = line

 後でFillメソッドを作成するために、オブジェクト名を保存しておきます。

taList &= "ta" & TableName & ","

 テーブルアダプタにUupdateメソッドがあるかどうかをチェックし(実際には、Deleteメソッドをチェックする方が簡単です)、後で使うためにテーブルアダプタを保存します。

    UpdateType = typ.GetMethod("Delete")
    If UpdateType IsNot Nothing Then
        UpdateList &= "ta" & TableName & ","
    End If
Next

 各テーブルアダプタに対してFillメソッドを呼び出すためのメソッドを作成します。

    DTE.ActiveDocument.Selection.EndOfLine()
    DTE.ActiveDocument.Selection.NewLine()
    'Add the Update methods
    For Each ta As String In UpdateList.Split(",")
        If ta.Length > 0 Then
            DTE.ActiveDocument.Selection.Text = "Public Sub Update" _
                + ta.Substring(2) + "()"
            DTE.ActiveDocument.Selection.NewLine()
            DTE.ActiveDocument.Selection.Text = ta & ".Update(" & _
               ta.Substring(2) & ");"
            DTE.ActiveDocument.Selection.NewLine()
        End If
    Next
    targetAssembly = Nothing
End Sub

 Northwindサンプルにこのコードを適用すると、次のコードが得られます。

Partial Class NorthwindDataSet
    Dim taCustomers As _
        New NorthwindDataSetTableAdapters.CustomersTableAdapter
    Dim taEmployees As _
        New NorthwindDataSetTableAdapters.EmployeesTableAdapter
    Dim taOrder_Details As _
        New NorthwindDataSetTableAdapters.Order_DetailsTableAdapter
    Dim taOrders As _
        New NorthwindDataSetTableAdapters.OrdersTableAdapter
    Dim taProducts As _
        New NorthwindDataSetTableAdapters.ProductsTableAdapter

    Public Sub FillAll()
        taCustomers.Fill(Customers)
        taEmployees.Fill(Employees)
        taOrder_Details.Fill(Order_Details)
        taOrders.Fill(Orders)
        taProducts.Fill(Products)
    End Sub
    Public Sub UpdateOrder_Details()
        taOrder_Details.Update(Order_Details)
    End Sub
    Public Sub UpdateOrders()
        taOrders.Update(Orders)
    End Sub
End Class

 ここで紹介したロジックについてご意見などがありましたら、ぜひお寄せください。データセットが有効な間はテーブルアダプタをインスタンス化したままにしておく方がいいのか(このオブジェクトのメモリヒットが高くなります)、必要になるたびに(プロセッサがこのオブジェクトのインスタンス化を要求するたびに)インスタンス化して、メモリをできるだけ解放しておく方がいいのか、意見はいろいろあると思います。今回の例では、インスタンス化したままにしておいたので、Update呼び出しでもそのまま使用できます。

次のページ
データベースプロバイダの非依存性

この記事は参考になりましたか?

japan.internet.com翻訳記事連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

David Catherman(David Catherman)

CMI Solutions所属。データベースアプリケーションのデザイン/開発に20年以上の経験を持ち、ここ4、5年は特にMicrosoft .NETとSQL Serverに仕事が集中している。現在はCMI Solutionsのアプリケーション設計者および上級開発者であり、Visual Studioと...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/348 2006/04/24 16:33

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー