2

新しく作成された (poco) エンティティを DbContext に追加して接続できるかどうかを知りたい (子オブジェクトをナビゲーションで遅延ロードできるようにするため)

var user = new User();
user.LocationID = 3;
dbContext.Users.Add(user);
var locationName = user.Location.Name;

(注: Location オブジェクトを取得して直接割り当てることができることを理解しています。上記の例は、この質問の目的のためだけのものです)

(注 II: プロキシ オブジェクトを作成してから値をコピーできます。そのようなオブジェクトは接続されます (そして遅延ロードを実行します) が、複雑な子オブジェクト (他の poco) はコピーに含まれません)

追加された poco を接続 (またはロード) する方法はありますか?

4

1 に答える 1

4

簡単な答えは、外部キーと POCO を使用する場合、次のように FK を設定した後に参照プロパティを明示的に遅延ロードできるということです。

context.Entry(e).Reference(propName).Load();

オブジェクト グラフを頻繁にトラバースする必要がある場合は、外部キー プロパティではなく概念レベルで作業する方が簡単かどうかを検討する価値があります。

ナビゲーション プロパティによって表されるエンティティがコンテキストによって追跡されている場合、FK プロパティと nav プロパティの同期は DetectChanges() で発生する可能性があります。ドキュメントは、これがオブジェクトに永続的なキーがある場合にのみ発生することを示唆しています。

参照が追加された状態 (この例ではコース オブジェクト) にある場合、SaveChanges が呼び出されるまで、参照ナビゲーション プロパティは新しいオブジェクトのキー値と同期されません。オブジェクト コンテキストには、追加されたオブジェクトが保存されるまで永続的なキーが含まれていないため、同期は行われません。

Addedただし、ドキュメントは正しくないか、誤解を招くようであり、永続的なキーを持たない状態にある新しく追加されたエンティティのプロパティを操作すると、nav プロパティと外部キーの同期が引き続き発生します。

以下は、これを調査するために使用した独自のデータ モデルのテスト コードです。これは、実際にはEF4.3であると理解している.Net4でEF5を使用しています。

using (MyContext context = new MyContext())
{
  /*
   * Uncomment these lines to test assigning FK Id when entity is being tracked
   */
  Customer cust1 = context.Customers.OrderBy(x => x.Id).First();
  Customer cust2 = context.Customers.OrderBy(x => x.Id).Skip(1).First();

  /*
   * Uncomment these lines to test assigning FK Id 
   * without having entity loaded in ObjectStateManager
   */
  //Customer cust1 = context.Customers.AsNoTracking().OrderBy(x => x.Id).First();
  //Customer cust2 = context.Customers.AsNoTracking()
  //                         .OrderBy(x => x.Id).Skip(1).First();

  //new entities
  Quote proxyQ = context.Quotes.Create();
  Quote pocoQ = new Quote();

  /*
   * if adding the new entities to context before setting FK properties
   * DetectChanges must be called later to attempt sync with nav props
   */
  context.Quotes.Add(proxyQ);
  context.Quotes.Add(pocoQ);

  //set FK Customer ids
  proxyQ.CustomerId = cust1.Id;
  pocoQ.CustomerId = cust2.Id;

  /*
   * FK / nav prop sync happens on DetectChanges() if the Customer 
   * entity is being tracked
   * it must be explicitly called if it has not been called using 
   * one of the AutoDetectChanges functions in order to sync
   */
  context.ChangeTracker.DetectChanges();

  /*
   * Alternatively, if the new entities are added to context after setting FK props
   * and AutoDetectChanges is enabled then DetectChanges is called implicitly and
   * FK / nav prop sync will happen here if the matching Customer entity is 
   * being tracked by the context.
   */
  //context.Quotes.Add(proxyQ); 
  //context.Quotes.Add(pocoQ);

  /*
   * If assigning FK Id and the entity the id represents is not tracked then 
   * proxy will lazy load Customer here.
   */
  Console.WriteLine("Proxy quote with key {0} linked to customer with name {1}",
   proxyQ.Id.ToString(), proxyQ.Customer != null ? proxyQ.Customer.Name : "null");

  /*
   * Obviously no lazy loading of Customer can occur here for a POCO
   */
  Console.WriteLine("POCO quote with key {0} linked to customer with name {1}",
   pocoQ.Id.ToString(), pocoQ.Customer != null ? pocoQ.Customer.Name : "null");

  /*
   * But we can explicit lazy load when using POCO if we have assigned 
   * an FK Customer Id to a POCO quote and the Customer entity is not 
   * being tracked by context
   */
   //context.Entry(pocoQ).Reference("Customer").Load();
   //Console.WriteLine("POCO quote with key {0} linked to customer with name {1}",
   //  pocoQ.Id.ToString(), pocoQ.Customer != null ? pocoQ.Customer.Name : "null");
于 2013-06-29T05:55:29.200 に答える