web-dev-qa-db-ja.com

DbSet.Attach(entity)vs DbContext.Entry(entity).State = EntityState.Modified

私が切り離されたシナリオにいて、それを保存するためにエンティティにマップするクライアントからdtoを取得するとき、これを行います:

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

それでは、DbSet.Attach(entity)

または、EntityState.Modifiedが既にエンティティをアタッチしているときに.Attachメソッドを使用する必要があるのはなぜですか?

95
Elisabeth

context.Entry(entity).State = EntityState.Modified;を実行すると、エンティティをDbContextにアタッチするだけでなく、エンティティ全体がダーティとしてマークされます。つまり、context.SaveChanges()を実行すると、EFはallフィールドを更新する更新ステートメントを生成しますエンティティの。

これは常に望ましいとは限りません。

一方、DbSet.Attach(entity)は、エンティティをコンテキストにアタッチしますwithoutそれをダーティとマークします。 context.Entry(entity).State = EntityState.Unchanged;を実行するのと同等です

この方法でアタッチする場合、エンティティのプロパティの更新を続行しない限り、次回context.SaveChanges()を呼び出すと、EFはこのエンティティのデータベース更新を生成しません。

エンティティの更新を計画している場合でも、エンティティに多くのプロパティ(db列)があり、いくつかの更新のみが必要な場合は、DbSet.Attach(entity)を実行してから、いくつかの更新のみを行うと有利な場合があります更新が必要なプロパティ。この方法で行うと、EFからより効率的な更新ステートメントが生成されます。 EFは、変更したプロパティのみを更新します(すべてのプロパティ/列が更新されるcontext.Entry(entity).State = EntityState.Modified;とは対照的)

関連ドキュメント: Add/Attach and Entity States

コード例

次のエンティティがあるとしましょう:

public class Person
{
    public int Id { get; set; } // primary key
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

コードが次のようになっている場合:

context.Entry(personEntity).State = EntityState.Modified;
context.SaveChanges();

生成されるSQLは次のようになります。

UPDATE person
SET FirstName = 'whatever first name is',
    LastName = 'whatever last name is'
WHERE Id = 123; -- whatever Id is.

実際に値を変更したかどうかに関係なく、上記の更新ステートメントがすべての列を更新する方法に注意してください。

対照的に、コードが次のような「通常の」アタッチを使用している場合:

context.People.Attach(personEntity); // State = Unchanged
personEntity.FirstName = "John"; // State = Modified, and only the FirstName property is dirty.
context.SaveChanges();

その場合、生成される更新ステートメントは異なります。

UPDATE person
SET FirstName = 'John'
WHERE Id = 123; -- whatever Id is.

ご覧のとおり、更新ステートメントonlyは、接続後に実際に変更された値を更新しますコンテキストのエンティティ。テーブルの構造によっては、これがパフォーマンスに良い影響を与える可能性があります。

さて、どのオプションがあなたにとって良いかは、あなたが何をしようとしているかに完全に依存します。

243
sstan

DbSet.Updateメソッドを使用すると、Entity FrameworkはエンティティのすべてのプロパティをEntityState.Modifiedとしてマークするため、それらを追跡します。すべてではなく一部のプロパティのみを変更する場合は、DbSet.Attachを使用します。このメソッドは、すべてのプロパティをEntityState.Unchangedにするため、更新するプロパティをEntityState.Modifiedにする必要があります。したがって、アプリがDbContext.SaveChangesにヒットすると、変更されたプロパティのみを操作します。

0
Orhun