2012-09-06 21 views
9

エンティティがDbContextの外で変更された場合(デタッチされたエンティティ)、エンティティの更新に関する小さな問題がありました。変更されたエンティティを添付すると、状態は変更されません。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にどのように伝えることができますか?

答えて

21

エンティティが接続後にmodifiedであることをEFに伝える必要があります。

context.Entry(specificationToSave).State = EntityState.Modified; 

また、あなたはそれを再び取り付けている、例えば後に実体に変更を加えることができます参照MVC3 with EF 4.1 and EntityState.Modified

編集

あなたはDbSetでジェネリックを使用することができます - のいずれかのクラス、またはメソッド - 次のように:

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

編集を:独立した親の更新のために/託児グラフ

効率性とパフォーマンスが重要ではない単純/浅い親子関係の更新では、単純にすべての古いχ ldrenと新しいものを再挿入するのは簡単です(醜いですが)。

しかし、より効率的なシナリオでは、グラフをトラバースして変更を検出し、新たに挿入し、既存の更新を追加し、変更を取り消し、削除したアイテムをContextに追加する必要があります。

スラマは、偉大な例であるof this hereを示しています。

GraphDiffを使用してみるとよいでしょう。これはあなたのためにこのすべての作業を行うことができます!

+1

多くのおかげで:-)それは私が探していたものです。 2番目の方法が最適ですが、この場合は不可能です。だから私は直接DbEntityEntryの状態を更新する必要があります。非常に素晴らしい解決策ではありませんが、機能します。 –

+0

'specificationToSave'のすべての関連するエンティティの状態を設定する必要がある場合は本当ですか?たとえば、私が 'specificationToSave'に変更された項目のリストを持っているとします。私は本当にそれを行うための簡単な解決策があることを願っています。 –

+0

@Jürgen親:子シナリオは、子供の追加、削除、または更新が必要な場合があるので、特別な配慮が必要です。 FWIW私は通常、子どもにハッシュを行い、変更があったかどうか、もしあれば、既存のものをすべて削除して、すべての子を再度挿入します。しかし、それだけで私は怠惰です。 – StuartLC