エンティティの関連付けの更新に問題があります。次のようなエンティティを取得すると:
MyContext context = new MyContext();
Person myPerson = context.PersonSet.FirstOrDefault();
String myPersonName = myPerson.Name;
Address myPersonAddress = myPerson.Address;
Addressという名前の関連付けとNameという名前のプロパティを持つ人物を取得しました。プロパティの名前など、データベース内のデータを手動で変更した場合、次のコードを使用してエンティティをリロードする必要があります。
context.Entry(myPerson).Reload();
そして、私は名前の新しい値を持っています。しかし、私がアドレスに対して同じことをすると、それは機能しません。これは、Addressが関連プロパティであるためだと思います。更新する必要があります。
Addressアソシエーション(およびPersonクラスの他のすべてのアソシエーション)を強制的に再ロードするにはどうすればよいですか?
編集:
同じケースで、人は複数のアドレスを持つことができます。
MyContext context = new MyContext();
Person myPerson = context.PersonSet.FirstOrDefault();
String myPersonName = myPerson.Name;
List<Address> myPersonAddresses = myPerson.Addresses;
この場合、それは参照ではありません:
context.Entry(myPerson).Reference(p => p.Address).Load();
// Address will be populated with only the new address
// this isn't required because I use lazy loading
しかしコレクション:
context.Entry(myPerson).Collection(p => p.Addresses).Load();
// Address will be populated with old value and new value
これを使用する必要があります:
context.Entry(myPerson).Collection(p => p.Addresses).CurrentValue.Clear();
context.Entry(myPerson).Collection(p => p.Addresses).Load();
しかし、私のすべてのナビゲーションプロパティに対してこれを行うには良い解決策ではないようです。
遅延読み込みを使用しない場合は、(最初にAddress
を読み込んだときに(たとえば、Include
を使用して)明示的に読み込む必要があったため、新しいPerson
を明示的に読み込みます。
context.Entry(myPerson).Reload();
// If the person refers to another Address in the DB
// myPerson.Address will be null now
if (myPerson.Address == null)
context.Entry(myPerson).Reference(p => p.Address).Load();
// myPerson.Address will be populated with the new Address now
遅延読み込みを使用する場合、2番目のコードブロックは必要ありません。それにもかかわらず、新しいmyPerson.Address
のプロパティにアクセスするとすぐに、データベースへの新しいクエリを取得します(上記の2番目のコードブロックに新しいクエリがあるように)。最初の行で、ナビゲーションプロパティが読み込まれていないとマークされます。人がDBの新しいアドレスを参照する場合。
この動作は、モデルクラスで外部キーを公開したかどうかには依存しません。
オブジェクトグラフ全体を1回の呼び出しで再読み込みおよび更新する単一の魔法のReload
メソッドを呼び出す方法はないようです(完全なオブジェクトグラフを熱心に読み込む単一のInclude
がないのと同様)。
ありがとうございました !
context.Entry(myPerson).Collection(p => p.Addresses).Load();
私のためにその仕事をしました。
P.Addressesが1つのエントリを失った場合、次の方法で更新できます。
((IObjectContextAdapter)CurrentContext(context)).ObjectContext.Refresh(RefreshMode.StoreWins, p.Addresses);
しかし、それが1つのエントリを取得した場合は、.Load()メソッドのみが役立ちました。再度、感謝します!
LINQ式を変更するには、 Query() 拡張を使用する必要があります。これは私の個人コードに基づく例です。このコードでは、myPersonオブジェクトの関連するAddressTypeナビゲーションプロパティを使用してAddressesコレクションを再読み込みし、結果をSomeListに配置します。
_DbContext.Entry<Person>(myPerson)
.Collection(i => i.Adresses) // navigation property for Person
.Query()
.Include("AddressType") // navigation property for Address
.OrderBy(i => i.Name)
.ThenBy(i => i.AddressType.AddressTypeName) // just an example
.Select(i => new someClass
{
SoomeField1 = i.SomeField1,
...
})
.ToList()
.ForEach(i => SomeList.Add(i)); // SomeList is a List<T>