エンティティの状態の操作Working with entity states

このトピックでは、追加し、コンテキストにエンティティを接続する方法、および Entity Framework が SaveChanges 中にこれらを処理する方法について説明します。This topic will cover how to add and attach entities to a context and how Entity Framework processes these during SaveChanges. Entity Framework で、コンテキストに接続されている、または未接続の N 層シナリオでは EF にどのような状態のエンティティを通知させることができますが、エンティティの状態であるか追跡処理されます。Entity Framework takes care of tracking the state of entities while they are connected to a context, but in disconnected or N-Tier scenarios you can let EF know what state your entities should be in. このトピックで紹介するテクニックは、Code First および EF Designer で作成されたモデルに等しく使用できます。The techniques shown in this topic apply equally to models created with Code First and the EF Designer.

エンティティの状態および SaveChangesEntity states and SaveChanges

EntityState 列挙体によって定義されている 5 つの状態のいずれかでエンティティができます。An entity can be in one of five states as defined by the EntityState enumeration. これらの状態は次のとおりです。These states are:

  • : 追加されたエンティティがコンテキストによって追跡されているが、データベースに存在しませんAdded: the entity is being tracked by the context but does not yet exist in the database
  • Unchanged: エンティティがコンテキストによって追跡されていると、データベースに存在して、プロパティの値が、データベース内の値から変更されていませんUnchanged: the entity is being tracked by the context and exists in the database, and its property values have not changed from the values in the database
  • 更新日時: エンティティがコンテキストによって追跡されていると、データベースに存在して、プロパティの値の一部またはすべてが変更されました。Modified: the entity is being tracked by the context and exists in the database, and some or all of its property values have been modified
  • 削除: エンティティがコンテキストによって追跡されていると、データベースに存在しますが、次回に SaveChanges が呼び出されたとき、データベースから削除とマークされています。Deleted: the entity is being tracked by the context and exists in the database, but has been marked for deletion from the database the next time SaveChanges is called
  • : デタッチされたエンティティがないコンテキストによって追跡されて、Detached: the entity is not being tracked by the context

SaveChanges はさまざまな状態のエンティティのさまざまな処理を行います。SaveChanges does different things for entities in different states:

  • SaveChanges では、変更されていないエンティティは変更されません。Unchanged entities are not touched by SaveChanges. 更新プログラムは、エンティティ、Unchanged 状態のデータベースには送信されません。Updates are not sent to the database for entities in the Unchanged state.
  • 追加エンティティは、データベースに挿入され、しになる変更されずに SaveChanges を返します。Added entities are inserted into the database and then become Unchanged when SaveChanges returns.
  • 変更されたエンティティは、データベースが更新され、しになる変更されずに SaveChanges を返します。Modified entities are updated in the database and then become Unchanged when SaveChanges returns.
  • 削除されたエンティティは、データベースから削除して、コンテキストからデタッチされますし。Deleted entities are deleted from the database and are then detached from the context.

次の例では、エンティティまたはエンティティ グラフの状態を変更できる方法を示します。The following examples show ways in which the state of an entity or an entity graph can be changed.

新しいエンティティをコンテキストに追加します。Adding a new entity to the context

新しいエンティティは、DbSet の Add メソッドを呼び出すことによって、コンテキストに追加できます。A new entity can be added to the context by calling the Add method on DbSet. これは、エンティティを Added 状態で、つまりことにはデータベースに挿入される、次回の SaveChanges が呼び出されるとします。This puts the entity into the Added state, meaning that it will be inserted into the database the next time that SaveChanges is called. 例えば:For example:

using (var context = new BloggingContext())
{
    var blog = new Blog { Name = "ADO.NET Blog" };
    context.Blogs.Add(blog);
    context.SaveChanges();
}

コンテキストに新しいエンティティを追加する別の方法では、Added にその状態を変更します。Another way to add a new entity to the context is to change its state to Added. 例えば:For example:

using (var context = new BloggingContext())
{
    var blog = new Blog { Name = "ADO.NET Blog" };
    context.Entry(blog).State = EntityState.Added;
    context.SaveChanges();
}

最後に、別のエンティティは既に追跡されている最大フックして、コンテキストに新しいエンティティを追加できます。Finally, you can add a new entity to the context by hooking it up to another entity that is already being tracked. 別のエンティティのコレクション ナビゲーション プロパティに新しいエンティティを追加するか、新しいエンティティをポイントする別のエンティティの参照ナビゲーション プロパティを設定することが考えられます。This could be by adding the new entity to the collection navigation property of another entity or by setting a reference navigation property of another entity to point to the new entity. 例えば:For example:

using (var context = new BloggingContext())
{
    // Add a new User by setting a reference from a tracked Blog
    var blog = context.Blogs.Find(1);
    blog.Owner = new User { UserName = "johndoe1987" };

    // Add a new Post by adding to the collection of a tracked Blog
    var blog = context.Blogs.Find(2);
    blog.Posts.Add(new Post { Name = "How to Add Entities" });

    context.SaveChanges();
}

追跡し、これらの新しいエンティティがまだ追加されているエンティティがないその他のエンティティへの参照を持つ場合、これらの例のすべてのことは、コンテキストにも追加され、次回 SaveChanges が呼び出されるとに、データベースに挿入されます。Note that for all of these examples if the entity being added has references to other entities that are not yet tracked then these new entities will also be added to the context and will be inserted into the database the next time that SaveChanges is called.

既存のエンティティをコンテキストにアタッチAttaching an existing entity to the context

ある場合は、データベースが、これは現在によって追跡されていないコンテキスト DbSet の Attach メソッドを使用してエンティティを追跡するためにコンテキストを指示に既にわかっているエンティティが存在します。If you have an entity that you know already exists in the database but which is not currently being tracked by the context then you can tell the context to track the entity using the Attach method on DbSet. エンティティは、コンテキストで変更されていない状態になります。The entity will be in the Unchanged state in the context. 例えば:For example:

var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };

using (var context = new BloggingContext())
{
    context.Blogs.Attach(existingBlog);

    // Do some more work...  

    context.SaveChanges();
}

変更されないことをデータベースに接続されているエンティティの他の操作を実行せずに SaveChanges が呼び出された場合に注意してください。Note that no changes will be made to the database if SaveChanges is called without doing any other manipulation of the attached entity. これは、エンティティが Unchanged 状態であるためにです。This is because the entity is in the Unchanged state.

既存のエンティティをコンテキストにアタッチする別の方法では、Unchanged にその状態を変更します。Another way to attach an existing entity to the context is to change its state to Unchanged. 例えば:For example:

var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };

using (var context = new BloggingContext())
{
    context.Entry(existingBlog).State = EntityState.Unchanged;

    // Do some more work...  

    context.SaveChanges();
}

これらの例の両方にアタッチされるエンティティがまだ追跡されていない他のエンティティへの参照を持つ場合、これらの新しいエンティティもに接続されている Unchanged 状態でコンテキストに注意してください。Note that for both of these examples if the entity being attached has references to other entities that are not yet tracked then these new entities will also attached to the context in the Unchanged state.

コンテキストに変更されたエンティティが、既存のアタッチAttaching an existing but modified entity to the context

ある場合は、どの変更可能性がありますが行われたエンティティをアタッチし、その状態を Modified に設定するコンテキストを指示するが、データベース内に既にわかっているエンティティが存在します。If you have an entity that you know already exists in the database but to which changes may have been made then you can tell the context to attach the entity and set its state to Modified. 例えば:For example:

var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };

using (var context = new BloggingContext())
{
    context.Entry(existingBlog).State = EntityState.Modified;

    // Do some more work...  

    context.SaveChanges();
}

Modified 状態を変更して、エンティティのすべてのプロパティは変更済みとしてマークはすべてのプロパティ値は、SaveChanges が呼び出されたときに、データベースに送信されます。When you change the state to Modified all the properties of the entity will be marked as modified and all the property values will be sent to the database when SaveChanges is called.

アタッチされるエンティティにまだ追跡されていない他のエンティティへの参照がある場合は、し、これらの新しいエンティティが接続されている Unchanged 状態でコンテキストに注意してください: ない自動的に行うことが変更されました。Note that if the entity being attached has references to other entities that are not yet tracked, then these new entities will attached to the context in the Unchanged state—they will not automatically be made Modified. 変更済みとしてマークする必要がある複数のエンティティがある場合の各エンティティの状態を個別に設定する必要があります。If you have multiple entities that need to be marked Modified you should set the state for each of these entities individually.

追跡対象エンティティの状態の変更Changing the state of a tracked entity

エントリに、State プロパティを設定して追跡されるエンティティの状態を変更することができます。You can change the state of an entity that is already being tracked by setting the State property on its entry. 例えば:For example:

var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };

using (var context = new BloggingContext())
{
    context.Blogs.Attach(existingBlog);
    context.Entry(existingBlog).State = EntityState.Unchanged;

    // Do some more work...  

    context.SaveChanges();
}

既に追跡されているエンティティの追加またはアタッチを呼び出すこともでき、エンティティの状態を変更するに注意してください。Note that calling Add or Attach for an entity that is already tracked can also be used to change the entity state. たとえば、Added 状態であるエンティティの Attach の呼び出しはその状態を変更 Unchanged。For example, calling Attach for an entity that is currently in the Added state will change its state to Unchanged.

挿入または更新パターンInsert or update pattern

一部のアプリケーションの一般的なパターンは、新しい (その結果、データベースの挿入) としてエンティティを追加するか、またはとして既存のエンティティをアタッチし、(その結果、データベースの更新) を変更済みとしてマークする主キーの値によって決まります。A common pattern for some applications is to either Add an entity as new (resulting in a database insert) or Attach an entity as existing and mark it as modified (resulting in a database update) depending on the value of the primary key. たとえば、データベースで生成された整数の主キーを使用する場合は、新規として 0 個のキーを持つエンティティと既存として 0 以外のキーを持つエンティティを処理する一般的なは。For example, when using database generated integer primary keys it is common to treat an entity with a zero key as new and an entity with a non-zero key as existing. このパターンは、主キーの値のチェックに基づくエンティティの状態を設定して実現できます。This pattern can be achieved by setting the entity state based on a check of the primary key value. 例えば:For example:

public void InsertOrUpdate(Blog blog)
{
    using (var context = new BloggingContext())
    {
        context.Entry(blog).State = blog.BlogId == 0 ?
                                   EntityState.Added :
                                   EntityState.Modified;

        context.SaveChanges();
    }
}

Modified 状態を変更すると、エンティティのすべてのプロパティは変更済みとしてマークされ、すべてのプロパティ値は、SaveChanges が呼び出されたときに、データベースに送信されますに注意してください。Note that when you change the state to Modified all the properties of the entity will be marked as modified and all the property values will be sent to the database when SaveChanges is called.