Entity Framework DataSource(EF DataSource)の強力なメカニズムを使用して、サーバーの関与なく、クライアント側で変更をキャンセルすることができます。この操作を「トランザクション」と呼びます。これは、複数の変更(作業単位)を全体として実行したりキャンセルすることができるという点で、この操作がデータベーストランザクションの一般的な概念に似ているためです。"全体として" とは、メモリ内のエンティティが不完全に、または一貫性なく変更されることがないということです。このようなトランザクションがデータベーストランザクションには何も影響を与えず、データベーストランザクションとは完全に独立していることを理解しておく必要があります。データベーストランザクションと区別するために、このトランザクションを「クライアント側トランザクション」と呼ぶことがあります。
クライアント側トランザクションは、[キャンセル]/[元に戻す]ボタン/コマンドの実装時に特に便利です。EF DataSource なしで操作をキャンセルしたり元に戻すには、オブジェクトコンテキスト内の変更をすべてキャンセルする必要があります。EF DataSource のクライアント側トランザクションでは、変更の一部をキャンセルすることができます。また、トランザクションはネストすることさえできます。たとえば、ダイアログボックスに[キャンセル]ボタンを置き(アプリケーションの他の場所で加えられた、オブジェクトコンテキスト内のすべての変更ではなく、ダイアログボックス内の変更だけをキャンセルするボタン)、そのダイアログボックスから、独自の[キャンセル]ボタンを持つ別のダイアログボックスを開くことができます。子ダイアログ内にネストされた(子)トランザクションを使用することで、その[キャンセル]ボタンから、子ダイアログボックスに加えられた変更だけをキャンセル(ロールバック)することができます。ユーザーは、親ダイアログボックスのデータの編集に戻り、親トランザクションを使用して、そのダイアログボックスで加えられた変更を受け入れたりキャンセルすることができます。
クライアント側トランザクションを最も簡単に使用するには、トランザクションをライブビューに関連付けます。たとえば、次のようにライブビューに連結されたデータグリッドがある場合は、
C# |
コードのコピー
|
---|---|
var ordersView = from o in customer.Orders.AsLive() select new OrderInfo { OrderID = o.OrderID, OrderDate = o.OrderDate, }; dataGrid1.ItemsSource = ordersView; |
次のようにトランザクションを作成して、ビューに関連付けることができます。
C# |
コードのコピー
|
---|---|
var transaction = _scope.ClientCache.CreateTransaction();
ordersView.SetTransaction(transaction);
|
子(ネストされた)トランザクションを作成するには、メソッド ClientCacheBase.CreateTransaction を呼び出す代わりに、ClientTransaction コンストラクタを使用し、パラメータとして親トランザクションを渡します。
C# |
コードのコピー
|
---|---|
var transaction = new ClientTransaction(parentTransaction);. |
View.SetTransaction|keyword=SetTransaction メソッド を呼び出してトランザクションをビューに関連付けたら、そのビューからデータ連結を通して加えられた変更(前述の例のように、エンドユーザーがビューに連結されたグリッドで変更を加えた場合など)やコードからプログラムを通して加えられた変更がすべて管理されます。ClientTransaction.Rollback を呼び出してトランザクションをロールバックすると、そのトランザクションによって管理されていた変更がキャンセルされます。
GUI コントロールをオブジェクトのコレクションではなく単一のオブジェクトに連結する場合もよくあります。単一のオブジェクトをライブビューで表すことはできないため、View.SetTransaction|keyword=SetTransaction メソッド を利用することはできません。この場合は、ClientTransaction.ScopeDataContext メソッドを使用します。WPF および Silverlight では、このメソッドを使用して DataContext を設定できます。XAML で指定されたデータ連結に対しては、次のように使用します。
DataContext = transaction.ScopeDataContext(order);
結果の DataContext は、元の DataContext をラップし、同じデータ連結を実行しますが、そのデータ連結を通して加えられた変更がすべて "トランザクション" として管理されるという利点があります。このため、必要に応じて、変更をロールバックすることができます。
WinForms の場合は、同じ ScopeDataContext を使用して、次のように結果のオブジェクトに連結することができます。
C# |
コードのコピー
|
---|---|
var dataContext = transaction.ScopeDataContext(order); textBox.DataBindings.Add(new Binding("Text", dataContext, "OrderDate")); |
最後に、ライブビューやデータ連結ではなく、コードを使用して一部のエンティティを変更(または追加/削除)し、その変更をトランザクションで管理する場合があります。それには、ClientTransaction.Scope() メソッドを使用します。このメソッドを使用すると、トランザクションのスコープが開きます。トランザクションのスコープにある間にエンティティを変更すると、変更がそのトランザクションによって管理されます。このメソッドは、次に示すように、終了時に自動的にスコープを閉じてくれる "using" 構文と共に使用するように設計されています。
C# |
コードのコピー
|
---|---|
using (transaction.Scope())
{
Customer.Orders.Add(order);
}
|
ここで説明したトランザクションを使用する3つの方法については、EF DataSource に付属する Transactions サンプルプロジェクトで具体例が示されています。このサンプルプロジェクトでは、子(ネストされた)トランザクションを使用して、[キャンセル]ボタンを持つフォームを、[キャンセル]ボタンを持つ別のフォームの内部に実装する方法についても説明しています。