15

エンティティが DbContext の外部で変更された場合 (デタッチされたエンティティである場合)、エンティティの更新に小さな問題があります。変更されたエンティティをアタッチすると、その状態は変更されません。

私のコードは次のようになります。

var specificationToSave = GetSpecificationFromTmpStore(userSessionGuid);
using (var context = DataContextFactory.GetDataContext())
{
    // this works for update, if I change the values inside the context while debugging
    // but it breaks with new entities
    context.Specifications.Attach(specificationToSave);

    // this works for insert new entities, modified entities will be saved as new entities
    context.Specifications.Add((specificationToSave);)
    context.SaveChanges();
}

私はNHibernateを知っており、それはSaveOrUpdateメソッドです。Hibernate は、エンティティを更新するか挿入するかを値に基づいて決定します。

EF 4.x および DbContext の外部で変更されたエンティティでこれを行うベスト プラクティスは何ですか? このエンティティが変更された状態であることを EF に伝えるにはどうすればよいですか?

4

2 に答える 2

29

既に変更されているエンティティに対してこのアプローチを使用する場合は、エンティティをアタッチした後に、エンティティが変更されAttachたことを EF に伝える必要もあります。

context.Specifications.Attach(entity);
context.Entry(entity).State = EntityState.Modified;
context.SaveChanges();

別の方法として、(追跡を使用して) フェッチし、フィールドを更新して保存することもできます。

var entity = context.Specifications.First(s => s.Id == 1234);
entity.Name = "Foo";
... other changes here
context.SaveChanges();

別のオプションは、エンティティを再アタッチしたにエンティティに変更を加えることです。

context.Specifications.Attach(entity);
entity.Name = "Foo";
... other changes here
context.SaveChanges();

編集

次のように、DbSet (クラスまたはメソッド) でジェネリックを使用できます。

public void Update<TEntity>(TEntity entity)
{
    DbContext.Set<TEntity>().Attach(entity);
    DbContext.Entry(entity).State = EntityState.Modified;
    DbContext.SaveChanges();
 }

編集:切り離された親/子グラフの更新用

効率とパフォーマンスが重要ではない、単純で浅い親子関係の更新では、古い子をすべて削除して新しい子を再挿入するだけで簡単に (見苦しくはありますが) 解決策になります。

ただし、より効率的なシナリオでは、グラフをトラバースし、変更を検出してから、新しく挿入された項目を追加し、既存のものを更新し、変更されていない項目を無視し、削除された項目を から削除する必要がありContextます。

Slauma は、ここでその好例を示しています。

GraphDiffを使用して、この脚の作業をすべて行うことができます。

于 2012-09-06T09:17:01.427 に答える