3

私はプロジェクトEF6 code firstで働いています。WinFormからエンティティを読み取りDb、更新してから に保存するために、次の方法を使用しましたDb

  1. を使用してエンティティグラフを読み取る ( disposesLinq to entitiesを読み取った後)DbContext
  2. 読み取っEntityたグラフをエンド ユーザーに表示します。
  3. エンド ユーザーは、この変更をEntityグラフ に適用できます。
    • ルート エンティティの更新
    • いくつかの子エンティティを追加
    • 一部の子エンティティを編集する
    • いくつかの子エンティティを削除します
  4. ユーザーがメソッドを呼び出して変更を永続化するDb
  5. 新しいDbContextインスタンスを作成します。
  6. Entity同じのグラフをリロードしますDb
  7. を使用して、すべてのプロパティの値をユーザー エンティティからリロードされたエンティティにマップします。AutoMapper
  8. 6 ステップの結果エンティティを my DbContextusingに添付しますGraphDiff
  9. DbContext.SaveChanges();への変更を保持するための呼び出しDb ここに画像の説明を入力

    var root = new MyDbcontext()
                               .Roots
                               .LoadAggregation()
                               .ToList();
                               //    LoadAggregation in this case, means following codes:   
                               //    .Include("Child1")   
                               //    .Include("Child2")
    
    root.Child1s.Remove(child11);
    root.Child1.Add(Child13); // 
    root.Child2.Add(Child22);
    using(var uow = new UnitOfWork())   
    {
        uow.Repository<Root>().Update(root);
        uow.Repository<AnotherRoot>().Update(anotherRoot); //user may want to update multiple Roots
        uow.SaveChanges();   <---- at this point Child13.Id and  Child22.Id generated by Db
    }
    

    public void Update(Root entity) //Update method in my Repository class
    { 
       var context = new MyDbcontext();
       var savedEntity = context.Roots //reload entity graph from db
                                .LoadAggregation()
                                .ToList();
       Mapper.Map(entity,savedEntity); // map user changes to original graph
       context.UpdateGraph(savedEntity, savedEntity.MappingConfiguration); // attach updated entity to dbcontext using graphdiff
    } 

    public void SaveChanges() // SaveChanges() in UnitofWork class
    {  
      context.SaveChanges();
    }

それはうまく動作します、

2 番目のグラフでは、ユーザーによって追加された Child13 と Child22 が呼び出され、uow.SaveChanges()それらが保存されDb、そのIds が割り当てられます。しかしChild13.Id、オブジェクトではChild22.Idまだ、手動でs を更新できますが、生成された s でこれらの値を更新する一般的な方法を探しています。entity0IdIdDbId

4

1 に答える 1

3

個人的には、少し違ったアプローチをとります。

このようなトランザクションは、複数のコンテキストにまたがってはなりません。これらの ID を手動で更新できたとしても、データベースによって割り当てられた ID とオブジェクト インスタンスを正しく同期させるために、それらの子オブジェクトを特定する別の方法が必要になります。または、これらのオブジェクトの他の側面が一時的に更新された可能性があり、データベースにも適用する必要があります。一般的に言えば、異なる DBContext からロードされたオブジェクトは、EF の上に何らかのキャッシュを実装していない限り、同じデータベース ID を持っていても、異なるオブジェクトです。

私はこのようなことをします。1 つのコンテキストを使用し、永続化操作を行う必要がある場所にコンテキストを挿入することで、EF がすべての識別を管理できるようにします。

var context = new MyDbcontext();
var root = context
                           .Roots
                           .LoadAggregation()
                           .ToList();
                           //    LoadAggregation in this case, means following codes:   
                           //    .Include("Child1")   
                           //    .Include("Child2")

root.Child1.Remove(child11);
root.Child1.Add(Child13); // 
root.Child2.Add(Child22);
using(var uow = new UnitOfWork())   
{
    uow.Repository<Root>().Update(root, context);
    uow.Repository<AnotherRoot>().Update(anotherRoot, context); //user may want to update multiple Roots
    uow.SaveChanges(context);   <---- at this point Child13.Id and  Child22.Id generated by Db
}

public void Update(Root entity, MyDbcontext context) //Update method in my Repository class
{ 
   var savedEntity = context.Roots //reload entity graph from db
                            .LoadAggregation()
                            .ToList();
   Mapper.Map(entity,savedEntity); // map user changes to original graph
   context.UpdateGraph(savedEntity, savedEntity.MappingConfiguration); // attach updated entity to dbcontext using graphdiff
} 

public void SaveChanges(context) // SaveChanges() in UnitofWork class
{  
  context.SaveChanges();
}

何らかの理由で同じコンテキストを使用できない場合は、Guid などの子オブジェクトに何らかの ID フィールドを追加し、データベースに永続化する前にそれを子オブジェクトに書き込むことを検討してください。 SaveChanges 経由。少なくとも、同期するオブジェクトを識別するためのかなり一貫した手段が必要です。

于 2014-08-13T22:54:34.303 に答える