DataSource for Entity Framework for WinForms
コードでのエンティティの操作
プログラミングガイド > コードでのエンティティの操作

DataSource for Entity Framework は、Entity Framework(または RIA)の通常のメソッドやプロパティを使用してコードで自由にエンティティを操作でき、それが C1DataSource との組み合わせで正しく機能するという意味で非侵入型です。通常のメソッドを使用してエンティティを追加、削除、および変更できます(そのために、特別な C1DataSource オブジェクトモデルは必要ありません)。また、エンティティに対して行った変更は、自動的に C1DataSource コレクションに反映されます。たとえば、新しいエンティティを追加するために何か特別な C1DataSource メソッドを使用する必要はなく、したがって存在もしません。いつも EF(または RIA)で行っているように、単に新しいエンティティを追加するだけで、対応する C1DataSource コレクションにそれが表示されます。C1DataSource コレクションが Where 条件を持つ場合は、その条件を満足する場合にのみ表示されます。同じことが、エンティティの削除や変更にも当てはまります。通常の EF(または RIA)の方法で削除や変更を行うと、C1DataSource に変更が自動的に反映され、したがって連結コントロールにも自動的に反映されます。

しかし、厳密に守る必要がある重要な制限が1つあります。実行できる内容は制限されません。(かなりまれな)いくつかのケースでのみ、実行する内容を C1DataSource に通知するためのメソッド呼び出しをコードに追加する必要があります。

DataSource に通知しないまま、コンテキストを直接クエリーしてサーバーからエンティティをフェッチしてはなりません。

すべてのエンティティは、C1DataSourceGetItems メソッドの1つを使用してフェッチするか、またはオブジェクトコンテキストを直接クエリーすることによってフェッチする場合は、ClientScope.AddRef メソッドを呼び出して、サーバーからエンティティをフェッチしたことを C1DataSource に通知する必要があります。

C1DataSource コントロールまたは ClientViewSource を使用する場合は、AutoLoad = true として暗黙的に、または ClientViewSource.Load メソッドを呼び出して明示的にエンティティをフェッチします。どちらの場合も C1DataSource を通してフェッチが実行されるため、C1DataSource は新しくフェッチしたエンティティを認識することができます。ClientViewSource を使用せずにコード内でエンティティをフェッチする必要がある場合は、C1DataSourceGetItems メソッド(EntityClientScope.GetItems メソッド、RiaClientScope.GetItems メソッド)の1つを使用する方法が標準的です。この場合も、C1DataSource はフェッチされたエンティティを認識できます。しかし、場合によっては、C1DataSource を使用せずに、サーバーに直接クエリーを発行することによってエンティティを取得する必要があることがあります。たとえば、Entity Framework では、次のように、C1DataSource によって使用される ObjectContext を取得して、クエリーを作成できます。

C#
コードのコピー
ObjectContext context = scope.ClientCache.ObjectContext;
        // または
ObjectQuery query = ((NORTHWNDEntities)context).Customers;
        // または
query = context.CreateObjectSet<Customer>();
        // または
query = context.CreateQuery<Customer>("...");

RIA サービスでは、次のようなコードになります。

C#
コードのコピー
DomainContext context = scope.ClientCache.DomainContext;
var query = ((DomainService1)context).Customers;
        // または
var entities = context.Load(
((DomainService1)context).GetCustomersQuery()).Entities;

クエリーを作成したら、クエリー結果を列挙することで、サーバーから直接エンティティを取得できます

foreach (Customer c in query) /* 何らかの処理 */

または、コントロールをクエリー結果に連結します。

C#
コードのコピー
dataGrid.ItemsSource = query;

ClientScope.AddRef を呼び出さずにこれを実行すると、サーバーからエンティティは取得できますが、C1DataSource はそれを認識できません。それらのエンティティは、他のエンティティと同じキャッシュに入り、区別できなくなります。したがって、C1DataSource は、それらを他のエンティティと同様に管理し、それらを解放したり、不要になれば破棄してしまう可能性があります。これによってエンティティはアクセスできなくなりますが、プログラムではまだ必要かもしれません。したがって、C1DataSource が管理するコンテキストに対して C1DataSource を使用せずにエンティティをフェッチし、エンティティをフェッチしたことを C1DataSource に通知しなければ、非常に不都合な問題が発生する可能性があります。幸い、その通知は簡単に追加できます。次のように、フェッチしたすべてのエンティティに対して ClientScope.AddRef を呼び出すだけです。

C#
コードのコピー
foreach (Customer c in query)
{
   scope.AddRef(c);
   // 何らかの処理
}

これは、C1DataSource に対して、スコープが有効な限りエンティティを解放できないことを通知します。