Entity Framework DataSource(EF DataSource)は、Entity Framework(または RIA)の通常のメソッドやプロパティを使用してコードで自由にエンティティを操作でき、それが EF DataSource との組み合わせで正しく機能するという意味で非侵入型です。通常のメソッドを使用してエンティティを追加、削除、および変更できます(そのために、特別な EF DataSource オブジェクトモデルは必要ありません)。また、エンティティに対して行った変更は、自動的に EF DataSource コレクションに反映されます。たとえば、新しいエンティティを追加するために何か特別な EF DataSource メソッドを使用する必要はなく、したがって存在もしません。いつも EF(または RIA)で行っているように、単に新しいエンティティを追加するだけで、対応する EF DataSource コレクションにそれが表示されます。EF DataSource コレクションが Where 条件を持つ場合は、その条件を満足する場合にのみ表示されます。同じことが、エンティティの削除や変更にも当てはまります。通常の EF(または RIA)の方法で削除や変更を行うと、EF DataSource に変更が自動的に反映され、したがって連結コントロールにも自動的に反映されます。
しかし、厳密に守る必要がある重要な制限が1つあります。実行できる内容は制限されません。(かなりまれな)いくつかのケースでのみ、実行する内容を EF DataSource に通知するためのメソッド呼び出しをコードに追加する必要があります。
注意
EF DataSource に通知しないまま、コンテキストを直接クエリーしてサーバーからエンティティをフェッチしてはなりません。
すべてのエンティティは、EF DataSource の GetItems メソッドの1つを使用してフェッチするか、またはオブジェクトコンテキストを直接クエリーすることによってフェッチする場合は、ClientScope.AddRef メソッドを呼び出して、サーバーからエンティティをフェッチしたことを EF DataSource に通知する必要があります。
C1DataSource コントロールまたは ClientViewSource を使用する場合は、AutoLoad = true として暗黙的に、または ClientViewSource.Load メソッドを呼び出して明示的にエンティティをフェッチします。どちらの場合も EF DataSource を通してフェッチが実行されるため、EF DataSource は新しくフェッチしたエンティティを認識することができます。ClientViewSource を使用せずにコード内でエンティティをフェッチする必要がある場合は、EF DataSource の GetItems メソッド(EntityClientScope.GetItems|keyword=EntityClientScope.GetItems メソッド、RiaClientScope.GetItems|keyword=RiaClientScope.GetItems メソッド)の1つを使用する方法が標準的です。この場合も、EF DataSource はフェッチされたエンティティを認識できます。しかし、場合によっては、EF DataSource を使用せずに、サーバーに直接クエリーを発行することによってエンティティを取得する必要があることがあります。たとえば、Entity Framework では、次のように、EF DataSource によって使用される 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; |
クエリーを作成したら、クエリー結果を列挙することで、サーバーから直接エンティティを取得できます。
C# |
コードのコピー
|
---|---|
foreach (Customer c in query) /* 何らかの処理 */ |
または、コントロールをクエリー結果に連結します。
C# |
コードのコピー
|
---|---|
dataGrid.ItemsSource = query; |
ClientScope.AddRef を呼び出さずにこれを実行すると、サーバーからエンティティは取得できますが、EF DataSource はそれを認識できません。それらのエンティティは、他のエンティティと同じキャッシュに入り、区別できなくなります。したがって、EF DataSource は、それらを他のエンティティと同様に管理し、それらを解放したり、不要になれば破棄してしまう可能性があります。これによってエンティティはアクセスできなくなりますが、プログラムではまだ必要かもしれません。したがって、EF DataSource が管理するコンテキストに対して EF DataSource を使用せずにエンティティをフェッチし、エンティティをフェッチしたことを EF DataSource に通知しなければ、非常に不都合な問題が発生する可能性があります。幸い、その通知は簡単に追加できます。次のように、フェッチしたすべてのエンティティに対して ClientScope.AddRef を呼び出すだけです。
C# |
コードのコピー
|
---|---|
foreach (Customer c in query) { scope.AddRef(c); // 何らかの処理 } |
これは、EF DataSource に対して、スコープが有効な限りエンティティを解放できないことを通知します。