エンティティのコンテキストへの添付 (Dynamics CRM 2015)

 

公開日: 2016年11月

対象: Dynamics CRM 2015

OrganizationServiceContext がエンティティと関係に対する変更を正しく追跡するためには、エンティティと関係をデータ コンテキストにアタッチする必要があります。 エンティティのクエリ、エンティティの更新、および変更の保存の標準パターンに従う場合は、エンティティのアタッチとデタッチを明示的に制御する必要はありません。 つまり、エンティティは取得時に自動的にコンテキストにアタッチされます。SaveChanges メソッドを呼び出した後で、OrganizationServiceContext によってすべてのエンティティがデタッチされることに注意してください。 以前に取得したエンティティに対してデータ コンテキストの使用を継続するには、エンティティを再アタッチする必要があります。 この操作は、エンティティの新しいセットを再クエリするか、エンティティで Attach メソッドを明示的に呼び出すことで実行できます。 Developer Extensions for Microsoft Dynamics CRM 2015 には、再アタッチ時にエンティティが正しい状態にあることを保証する ReAttach メソッドが用意されています。 この例を次に示します。

using Microsoft.Xrm.Client;

using (var service = new OrganizationService(connection))
using (var context = new OrganizationServiceContext(service))
{
var contact = context.CreateQuery<Contact>().First(c => c.FirstName == "Bob");
contact.JobTitle = "Developer";
context.UpdateObject(contact);
context.SaveChanges();

// contact is no longer attached at this point so reattach it
context.Reattach(contact);

contact.EMailAddress1 = "bob@contoso.com";
context.UpdateObject(contact);
context.SaveChanges();
}

再アタッチの必要性を回避するために、SaveChanges の 1 回の呼び出しですべての変更を適用してから、コンテキストを破棄することをお勧めします。

CrmOrganizationServiceContext は、SaveChanges の呼び出し後にエンティティを自動的に再アタッチすることで、このシナリオを簡略化します。AddObject 操作または UpdateObject 操作の入力パラメーターとして使用されるエンティティのみに再アタッチのフラグが付けられます。

using (var service = new OrganizationService(connection))
using (var context = new CrmOrganizationServiceContext(service))
{
var contact = context.CreateQuery<Contact>().First(c => c.FirstName == "Bob");
contact.JobTitle = "Developer";
context.UpdateObject(contact);
context.SaveChanges();
contact.EMailAddress1 = "bob@contoso.com";
context.UpdateObject(contact);
context.SaveChanges();
}

複数データ コンテキスト

エンティティ追跡の慎重な管理が必要な別のシナリオは、複数のデータ コンテキストで共通エンティティ オブジェクトを処理する場合です。 たとえば、1 つのコンテキストがエンティティを取得し、2 つ目のコンテキストがエンティティを更新する場合です。 エンティティが 2 つ目のコンテキストによって変更される前に、そのコンテキストにエンティティをアタッチする必要があります。 エンティティをアタッチできるのは 1 つのコンテキストのみであるため、2 つ目のコンテキストにアタッチする前にソース コンテキストからエンティティをデタッチする必要があります。

using (var service = new OrganizationService(connection))
using (var context1 = new OrganizationServiceContext(service))
{
var contact = context1.CreateQuery<Contact>().First(c => c.FirstName == "Bob");

using (var context2 = new OrganizationServiceContext(service))
{
context1.Detach(contact);
context2.Attach(contact);

contact.EMailAddress1 = "bob@contoso.com";
context2.UpdateObject(contact);
context2.SaveChanges();
}
}

コンテキストからのエンティティのデタッチ

デタッチすると破損する変更の複雑なグラフにエンティティが既に関連している可能性があるため、元のコンテキストからエンティティをデタッチすることが望ましくない場合があります。 より安全なアプローチは、2 つ目のコンテキストでエンティティの別のインスタンスを再取得し、元のエンティティには触れないことです。 このアプローチのバリエーションとして、元のエンティティのディープ クローンを作成し、クローン エンティティを 2 つ目のコンテキストにアタッチする方法もあります。AttachClone<T> および MergeClone<T> ヘルパー メソッドは後者のアプローチを採用し、MergeClone<T> は対象コンテキストにエンティティがまだアタッチされていないことを追加で確認します。

using (var service = new OrganizationService(connection))
using (var context1 = new OrganizationServiceContext(service))
{
var contact = context1.CreateQuery<Contact>().First(c => c.FirstName == "Bob");

using (var context2 = new OrganizationServiceContext(service))
{
var contact2 = context2.MergeClone(contact);

contact2.EMailAddress1 = "bob@contoso.com";
context2.UpdateObject(contact2);
context2.SaveChanges();
}
}

関連項目

Attach
SaveChanges
AddObject
UpdateObject
Developer Extensions のコンテキスト オブジェクト モデル (Dynamics CRM 2015)
構成ファイルを使用したコンテキストの構成 (Dynamics CRM 2015)
エンティティの関連付けへのアクセス (Dynamics CRM 2015)

© 2017 Microsoft. All rights reserved. 著作権