パート3 − ビジネス層の作成
本シリーズのパート1とパート2では、オブジェクト指向プログラミングに重点を置いて、Visual StudioのRAD(Rapid Application Development)ツールを使って3層アプリケーションを作成する方法について説明しました。個々のビジネスプロジェクト内に型指定されたデータセット(Typed DataSet)オブジェクトを作成し、プレゼンテーション層内にオブジェクトデータソースツールを作成することによって、アプリケーションの各部を別々の層に分離し、個別にコンパイルできるようにします。このようにして分離したコンポーネントは、必要に応じて異なるサーバーに配置することも可能です。
ドメインモデルアーキテクチャ
アーキテクチャモデルにはさまざまな種類がありますが、Microsoft Visual Studioが推奨する方法論に適しているのは、リレーショナルアーキテクチャと真のオブジェクト指向アーキテクチャの中間に位置するアーキテクチャです。このアーキテクチャは、Jimmy Nilssonをはじめとする著名な設計者によって推進されており、「ドメインモデルアーキテクチャ」と呼ばれています。このモデルでは、ドメイン層をビジネス層の奥深くに隠すのではなく、さまざまな別の階層からアクセス可能な位置まで引き上げます。図1に、このモデルとVisual Studio 2005がどのように対応しているかを示します。
図1 ドメインモデルアーキテクチャとVS2005の実装
このモデルでは、型指定されたデータセット(Typed DataSet)をドメイン層として使用します。型指定されたデータセットは、ほぼ純粋なオブジェクト指向方式のデータアクセスを行うことを目的として、データセット(DataSet)オブジェクトを一連のクラス、メソッド、およびプロパティでラップしたものであり、Intellisenseに対応しています。Visual Studio 2005では、これらのクラスは、パーシャルクラス内のデータセットの自動生成されたデザイナサブファイルに格納されます。もう1つのパーシャルクラスは、開発者がカスタマイズできるサブファイルの中で提供されます。これは、データに影響を及ぼすビジネスロジックを実装するのに適した場所です。
自動生成されたデザイナサブファイルでは、データベース内のデータの取得/更新に必要なすべてのADOコードを提供するデータアクセスロジックが別の名前空間に実装されています。この自動生成されたクラスはテーブルアダプタ(Table Adapter)と呼ばれます。これは、厳密に型指定されたプロパティとメソッドによってラップされたデータアダプタです。これらのクラスは自動生成されますが、テーブルアダプタのパーシャルクラスにコードを追加すれば拡張できます。
最初に生成した時点で、データセットはデータベースの構造またはスキーマを非常に密接にミラー化しています。データセットがデータベースに連動し過ぎると不満を述べる設計者もいますが、実際には、メタデータが表現されているだけです。必要であれば、すべてのテーブルとフィールドを、実際のエンティティと列をよりよく表すような名前に変更することも可能です。ただし、データベースが適切に設計されていれば、通常、このような操作は不要です。
ビジネス層の追加
ビジネスロジックでパーシャルクラスを使用するという手法は、データを直接処理する小規模なコードに適しています。企業開発者の多くは、各エンティティのロジックをそれぞれ個別のクラスとして実装することを好みます。私は現在、ビジネスオブジェクトを多用するKevin McNeishのMere Mortals Frameworkを使って作業をしています。このフレームワークでは、型指定されたデータセットを本稿の例と同じくらい簡単に使用でき、独立したビジネスオブジェクトクラスをインスタンス化して、既存のデータセット内のデータテーブルを参照します。この方法だと、すべてのビジネスロジックを含むビジネスオブジェクトクラスを作成できるので再利用性が高まる上に、データソースウィザードを使って画面を簡単に作成することができます。
ビジネスロジック
本シリーズのパート2で説明したように、ビジネスロジックの重要なポイントの1つは、いかにしてデータアクセス層を呼び出すかです。まず、個々のテーブルアダプタをインスタンス化し、データセット内のデータテーブルにデータを読み込むメソッドを用意する必要があります。これらのテーブルは更新可能なので、更新内容をデータベースに渡すメソッドも用意しなければなりません。パート2の例に示した5つのテーブルから成るNorthwindデータセットの場合、必要なデータアクセスコードは次のようになります。
Imports ta = NorthwindDataSetTableAdapters
Partial Public Class NorthwindDataSet
Private taOrders As New ta.OrdersTableAdapter
Private taOrderDetail As New ta.Order_DetailsTableAdapter
Private taCustomer As New ta.CustomersTableAdapter
Private taEmployee As New ta.EmployeesTableAdapter
Private taProduct As New ta.ProductsTableAdapter
Public Sub FillDataSetAll()
Me.taOrders.Fill(Me.Orders)
Me.taOrderDetail.Fill(Me.Order_Details)
Me.taCustomer.Fill(Me.Customers)
Me.taEmployee.Fill(Me.Employees)
Me.taProduct.Fill(Me.Products)
End Sub
Public Sub UpdateOrders()
Me.taOrders.Update(Me.Orders)
End Sub
Public Sub UpdateOrderDetails()
Me.taOrderDetails.Update(Me.Order_Details)
End Sub
End Class
これはごく簡単な例であり、データベース内の全レコードをデータテーブルに読み込んでいます。大きなデータベースの場合は、読み込むレコードをフィルタパラメータで制限します。
パラメータ付きクエリ
これまでご紹介しませんでしたが、データセットデザイナにはパラメータ付きクエリを追加できる機能があります。この機能を使うと、テーブル内のすべてのレコードが必要でないときに、目的のデータだけを取得できます。データセットを開き、いずれかのテーブルアダプタのヘッダーを右クリックすると、使用できる機能の一覧が表示されます。[Add Query]オプションをクリックするとテーブルアダプタ構成ウィザードが表示され、SQL文の使用、ストアドプロシージャの新規作成、既存のストアドプロシージャの使用というオプションが表示されます。単純なクエリの場合はSQL文を使ってもかまいませんが、セキュリティを要する環境では、ストアドプロシージャを使ってデータにアクセスするのがよいでしょう。ウィザードで生成されるものでも十分ですが、データベース管理者が作成したストアドプロシージャも使用できます。既存のストアドプロシージャを使用する場合は、この次の画面で、データベース内のすべてのストアドプロシージャのリストから選択できます。
次の画面では、クエリの使用目的を選択します。具体的には、行セットの選択、単一の値を返す、更新、削除、挿入の中から選択します。ほとんどの場合、クエリは行セットを返しますが、クエリによって更新や削除の方法を変更することもできます。
各クエリはSQL文で定義します。この画面でSQL文を手入力することも、標準のクエリビルダを使ってビジュアルに作成することもできます。
この時点で、特定の顧客のオーダーだけを取得するフィルタパラメータをクエリに追加できます。
ウィザードの次の画面では、FillByタイプのメソッド(既存のデータテーブルを使用する場合)とGetDataByタイプのメソッド(データテーブルオブジェクトを返す)の名前を編集できます。[Finish]ボタンをクリックすると、クエリが完成します。
データセットデザイナにより、テーブル表現のテーブルアダプタセクションに新しいメソッドの行が追加されます。CustomerIDパラメータを渡してFillByCustomerIDメソッドを呼び出すと、オーダーの一部だけをデータテーブルに読み込むことができます。
オプションパラメータの使用
テーブルアダプタに柔軟性を与えるもう1つの方法は、オプションパラメータを使用し、ユーザーが1回の呼び出しで複数のパラメータを選択できるようにすることです。今回のサンプルでは、次に示すように、WHERE節にOR @Parameter IS NULLを追加することによって、1つのクエリでCustomerIDまたはEmployeeIDを使って読み込みレコードを制限できるようにしています。
SELECT *
FROM Orders
WHERE (CustomerID = @CustomerID OR @CustomerID IS NULL)
AND (EmployeeID = @EmployeeID OR @EmployeeID IS NULL)
AND NOT (@CustomerID IS NULL AND @EmployeeID IS NULL)
この例では、いずれかのパラメータまたは両方のパラメータを渡すことができますが、何も渡さなかった場合は、空の結果セットが得られます。
型指定されたデータセットは、オプションパラメータを適切に処理します。ジェネレータは値型に対してNullable(型)パラメータを作成し、それをdbnullに正しく変換します。
型指定されたデータセットにおけるオプションパラメータの唯一の欠点は、自分自身でパラメータコレクションに対処しなければならないことです。ほとんどの場合、AllowDBNullプロパティを手動で設定する必要があり、クエリを再構成するたびにウィザードがその状態をリセットします。
リレーションを使ってテーブルにデータを読み込む
「Orders」テーブル内のレコード数を制限したため、「Order Details」テーブルにデータを読み込むときにも行数を制限しなければなりません。リレーションシップによる読み込み機能が追加されていればよいのですが、このバージョンには用意されていません。従って、自分で対処する必要があります。
ストアドプロシージャを使っている場合は、SQL Server 2005のMARS(Multiple Active Result Sets)機能を使って、一度に両方のテーブルにデータを返すことができます。結果セットを正しいデータテーブルにマップする特別なコードを追加する必要がありますが、それは大して難しくありません。このコードを記述するにはテーブルアダプタのパーシャルクラスを使用するとよいでしょう。テーブルアダプタのパーシャルクラスでは、データアダプタオブジェクトにアクセスしてTableMappingsメソッドを追加できるからです。
図7 リレーションに基づいてOrder Detailsにデータを読み込むクエリ
あるいは、「Orders」テーブル内のレコードをループ処理し、複数のOrderIDを区切り文字で連結した文字列を作成して、それをIN()句フィルタで使うパラメータとして渡すという方法もあります。しかし、IN()句は変数を受け取らないので、OrderIDのリストをSQL文と直接組み合わせ、そのSQL文をEXEC関数で実行する必要があります。
最も簡単なソリューションは、もう1つ別のクエリを「Order Details」テーブルアダプタに追加することです。このクエリでは、関係する2つのテーブルを結合し、図7のクエリビルダに示されているCompanyIDでフィルタするという処理を行います。このようなクエリは、「Order Details」テーブルを定義するプライマリクエリとしては正しく動作しません。なぜなら、更新時に更新対象のテーブルを見つけることが難しいからです。しかし、セカンダリクエリであれば適切に動作します。
複数のテーブルの更新
前の記事では、データセットを更新してデータベースに戻す非常に単純な手順を紹介しました。しかし、関連テーブルを更新する場合、更新メソッドには特別な注意が必要です。テーブルを間違った順序で更新すると、子レコードの前に親レコードを削除しようとしたり、親レコードを挿入する前に子レコードを挿入しようとしたりします。
関連テーブルを更新する場合の正しい順序は、1)削除される子レコードを送信する、2)親テーブルを更新する、3)子レコードを更新および追加する、というものです。この処理を実現するにはデータテーブルのGetChangesメソッドを使用します。今回の例では、まず新しい一時データテーブルを作成し、そのテーブルを、レコードの追加先または削除元となる現在のデータテーブルのサブセットとして定義します。その後、それぞれの一時データテーブルを正しい順序で更新します。
注意
この形式のコードは、VBコードスニペットに含まれています。
Public Sub UpdateDB()
Dim DeletedChildRecords As DataTable = _
Me.Order_Details.GetChanges(DataRowState.Deleted)
Dim NewChildRecords As DataTable = _
Me.Order_Details.GetChanges(DataRowState.Added)
Dim ModifiedChildRecords As DataTable = _
Me.Order_Details.GetChanges(DataRowState.Modified)
Try
If Not DeletedChildRecords Is Nothing Then
taOrderDetail.Update(DeletedChildRecords)
DeletedChildRecords.Dispose()
End If
taOrders.Update(Me.Orders)
If Not ModifiedChildRecords Is Nothing Then
taOrderDetail.Update(ModifiedChildRecords)
ModifiedChildRecords.Dispose()
End If
If Not NewChildRecords Is Nothing Then
taOrderDetail.Update(NewChildRecords)
NewChildRecords.Dispose()
End If
Me.AcceptChanges()
Catch ex As Exception
Throw ex
End Try
End Sub
他のビジネスロジックの追加
データセットのパーシャルクラスは、実際のデータアイテムを処理するビジネスロジックを実装するのに最適な場所です。今回の例では、テーブルアダプタをインスタンス化するのにデータセットのパーシャルクラスを使用しましたが、各テーブル(行コレクション)、テーブルの個々の行、行変更イベントについてもサブパーシャルクラスがあります。データセットのパーシャルクラスの外部では、各テーブルアダプタのパーシャルクラスにもアクセスできます。
例えば、同じ顧客の2つのオーダーを統合するために、あるOrderのすべてのOrder Detailレコードを別のOrderに移動するメソッドを作成するとします。この場合は、データセットのパーシャルクラス内に次のクラス(サブクラス)を作成できます。
Partial Public Class OrdersDataSet
...
Partial Public Class Order_DetailsDataTable
Public Sub MoveDetailRecords(ByVal FromOrderID As Integer,
ByVal ToOrderID As Integer)
For Each row As Order_DetailsRow In Me.Select( _
"OrderID=" & FromOrderID)
row.OrderID = ToOrderID
Next
End Sub
End Class
...
End Class
フォームコードに戻ると、新しいメソッドがIntellisenseのリストに表示されるようになります。
図8 カスタマイズされたメソッドがIntellisenseに表示される
もう1つの例として、顧客の住所情報をオーダーの出荷先セクションにコピーするメソッドを考えてみましょう。
Partial Public Class OrdersRow
Public Sub ShipToCustomer()
If Me.CustomerID Is Nothing Then
’TODO: should throw an exception
MsgBox("Customer not defined")
Return
End If
Dim CustTable As CustomersDataTable = _
Me.Table.DataSet.Tables("Customers")
Dim CustRow As CustomersRow = _
CustTable.FindByCustomerID(Me.CustomerID)
Me.ShipName = CustRow.ContactName
Me.ShipAddress = CustRow.Address
Me.ShipCity = CustRow.City
Me.ShipRegion = CustRow.Region
Me.ShipPostalCode = CustRow.PostalCode
Me.ShipCountry = CustRow.Country
End Sub
End Class
フォームコード内でOrderRowオブジェクトへの参照を取得すると、このShipToCustomerメソッドを使って出荷先住所をコピーすることができます。
ここで紹介したのは、データセットのパーシャルクラス内でビジネスロジックを作成する方法の2つの例に過ぎません。この方法の利点は、すべてのデータセットオブジェクトをコンテキスト内で使用できることです。別のクラスをビジネスオブジェクトとして作成する場合は、データオブジェクトにアクセスするためにデータセットへの参照を渡す必要があります。上記の例は、データセットオブジェクト内のコードなので、データオブジェクトを「Me」として参照できます。
マクロを使ってデータアクセスコードを生成する
データアクセス層のコードは、テーブル名が異なるだけで繰り返しが多いので、コードの自動生成に適しています。コードジェネレータにはさまざまな種類があり、それぞれに長所と短所があります。私は最近、マクロを使ってコードを生成する方法を調べています。この方法の長所は、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 & "bindebug" & 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呼び出しでもそのまま使用できます。
データベースプロバイダの非依存性
Microsoftは、プロバイダパターンを利用してさまざまなバックエンドエンジン間を切り替える機能をテーブルアダプタロジックに追加していません。プロバイダパターンは、抽象ファクトリパターンを中心とする組み合わせであり、アプリケーションを再コンパイルせずにバックエンドを切り替える機能を効率的に実現します。このパターンは、DotNetNuke、ASP.NET、およびその他のいくつかのMicrosoftテクノロジで使用できますが、生成されたテーブルアダプタには対応していません。しかし私は、データベースに依存しないアプリケーションを開発するという目的を達成するために、これを実現するストラテジを追求し続けてきました。
まず最初は、接続文字列を別のソースに変更して、データセットの再生成を試みました。データセットジェネレータは古いADO接続型を使おうとするので、これはうまくいきませんでした。しかし、別のデータベースへの接続を作成し、データセットジェネレータの内部で、各テーブルがポイントする接続を変更すれば、テーブルを再生成できます。
引き続きNorthwindsの例を使って説明を続けます。このサンプルデータベースは、MS Access、FoxPro、およびSQL Serverで提供されています。この手順を紹介するために、本稿のサンプルアプリケーションを、AccessデータベースとSQL Serverデータベースで動作するように変換します。最初からSQL Server接続にOLEDBプロバイダを使用していれば、それほど複雑な話ではないのですが、このデモンストレーションでは、Accessデータベースに対してはOLEDBプロバイダを使用し、SQL Serverに対しては引き続きSQLClientプロバイダを使用します。
本稿のサンプルアプリケーションは、現在、SQL Server接続で動作するように構成されています。これをAccess接続に変更する前に、元の状態を簡単に復元できるように、現在の構成を保存しておきましょう。データセットを開き、デザイナコードファイルを開きます(データセットの下のサブファイルを表示するには、ソリューションエクスプローラの上部にある[Show All Files]をオンにする必要がある場合があります)。デザイナファイルには、Partial Public Class OrdersDataSetおよびNamespace OrdersDataSetTableAdaptersという2つの主要なセクションがあります。クラスを修飾する属性が数行にわたって指定されていますが、余白内のマイナス記号をクリックしてセクションを折りたたむと、2つのセクションが表示されます。
テーブルアダプタのセクションを強調表示して[Ctrl]+[C]キーを押すと、セクション全体がコピーされます。プロジェクト内に新しいClassモジュールを作成し、「OrdersDataSetTableAdapters.SQL」という名前を指定し、コピーしたコードを貼り付けます。もちろん、重複するためこのままではエラーになりますが、末尾に「.SQL」を付けて名前空間を変更すれば、問題なくコンパイルできます。
次に、データセットデザイナのOrdersデータセットに戻り、「Orders」テーブルを右クリックし、[Configure...]を選択します。ウィザードの3ページ目が表示されますが、[Previous]ボタンを2回クリックして、接続を定義する先頭ページに戻ります。Accessデータベースの接続を選択するか、[New Connection]ボタンをクリックして新しい接続を作成します。ここで追加する接続は、プロジェクト設定と「App.Config」ファイルに記録されます。
接続文字列を変更したら、操作を続けて、構成ウィザードを終了します。テーブルアダプタがAccessデータベースをポイントするように変更されます。
データセット内のテーブルごとにこの手順を続けると、アプリケーションが、SQL ServerデータベースではなくAccessデータベースを使用するように変換されます。アプリケーションを実行すると、Accessデータが表示されます。疑うなら、情報の一部を変更して、AccessテーブルとSQL Serverテーブルのどこが変更されたかを確認してみてください。
次に、デザイナファイルからテーブルアダプタのセクションを取得し、「OrderDataSetTableAdapters.Jet」という名前の新たなClassモジュールを作成し、コードを貼り付けます。今回は、末尾に「.Jet」を付けて名前空間を変更します。
Developersパーシャルクラスファイルの先頭にあるImports文の名前空間の拡張子を変更するだけで、AccessとSQL Serverを相互に切り替えることができます。「.Jet」を追加すると、テーブルアダプタが、Accessとの接続用のコードをポイントします。
Imports ta = NorthwindDataSetTableAdapters.Jet
Partial Public Class NorthwindDataSet
Private taOrders As New ta.OrdersTableAdapter
Private taOrderDetail As New ta.Order_DetailsTableAdapter
...
これは、正しい方向に向けた大きな一歩ではありますが、拡張子の変更後にプロジェクトをビルドしなければならないため、最終的なソリューションではありません。本当のプロバイダパターンならば、「App.Config」ファイル内のパラメータを変えるだけで変更が可能であり、再コンパイルの必要はありません。私は引き続きこの問題に取り組み、今後の記事の中でソリューションを紹介したいと考えています。よいアイディアがあれば、ぜひお知らせください。
まとめ
Visual Studio 2005では、データアプリケーションの開発が驚くほど容易になりました。最終的には実際のリリースバージョンを使っていますが、ここでの開発はすべて、ベータ版で行われています。特筆すべき変更の1つは、デザイナコード内の各クラスに追加された新しい属性です。テーブルアダプタの処理に関する問題の1つとして、これらがどの基本クラスからも継承されず、インターフェイスも実装しないため、オブジェクト指向の手法を適用しにくいことが挙げられます。属性が導入されたことで、CodeDomとリフレクションを使って、操作に必要なリンクが提供されるはずです。何が起きているかについては、今後の記事で明らかにしていきます。
データベースアプリケーションのデザイン/開発に20年以上の経験を持ち、ここ4、5年は特にMicrosoft .NETとSQL Serverに仕事が集中している。現在はCMI Solutionsのアプリケーション設計者および上級開発者であり、Visual StudioとSQL Server 2005を使用している。.NETのMCPを取得し、現在MCSDを取得中。
メールの宛先はDCatherman@CMiSolutions.com。