Arbeiten mit Entitätszuständen

In diesem Artikel wird erläutert, wie Sie Entitäten zu einem Kontext hinzu- und anfügen. Außerdem erfahren Sie, wie Entity Framework diese während der SaveChanges-Methode verarbeitet. Mit Entity Framework wird der Status von Entitäten nachverfolgt, während sie mit einem Kontext verknüpft sind. In getrennten oder n-schichtigen Szenarios können Sie jedoch EF mitteilen, in welchem Zustand sich Ihre Entitäten befinden sollten. Die in diesem Thema dargestellten Techniken gelten jeweils für Modelle, die mit Code First und dem EF-Designer erstellt wurden.

Entitätszustände und die SaveChanges-Methode

Eine Entität kann sich in einem von fünf Zuständen befinden, die durch die EntityState-Enumeration definiert sind. Folgende Status sind möglich:

  • Added: Die Entität wird vom Kontext nachverfolgt, ist aber noch nicht in der Datenbank vorhanden.
  • Unchanged: Die Entität wird vom Kontext nachverfolgt und ist in der Datenbank vorhanden, und ihre Eigenschaftswerte unterscheiden sich nicht von den Werten in der Datenbank.
  • Modified: Die Entität wird vom Kontext nachverfolgt und ist in der Datenbank vorhanden, und einige oder alle zugehörigen Eigenschaftswerte wurden geändert.
  • Deleted: Die Entität wird vom Kontext nachverfolgt und ist in der Datenbank vorhanden, wurde jedoch für das Löschen aus der Datenbank beim nächsten Aufrufen der SaveChanges-Methode markiert.
  • Detached: Die Entität wird nicht vom Kontext nachverfolgt.

Die SaveChanges-Methode führt unterschiedliche Aktionen für Entitäten in verschiedenen Zuständen aus:

  • Entitäten mit dem Status „Unchanged“ werden von der SaveChanges-Methode nicht berücksichtigt. Updates werden nicht an die Datenbank von Entitäten mit dem Status „Unchanged“ gesendet.
  • Entitäten mit dem Status „Added“ werden in die Datenbank eingefügt und dann beim Zurückgeben der SaveChanges-Methode zu „Unchanged“.
  • Entitäten mit dem Status „Modified“ werden in der Datenbank aktualisiert und dann beim Zurückgeben der SaveChanges-Methode zu „Unchanged“.
  • Entitäten mit dem Status „Deleted“ werden aus der Datenbank gelöscht und dann vom Kontext getrennt.

In den folgenden Beispielen wird gezeigt, wie der Status einer Entität oder eines Entitätsgraphs geändert werden kann.

Hinzufügen einer neuen Entität zum Kontext

Eine neue Entität kann dem Kontext hinzugefügt werden, indem die Add-Methode für die DbSet-Klasse aufgerufen wird. Dadurch wird die Entität in den Status „Added“ versetzt, das heißt, sie wird beim nächsten Aufrufen der SaveChanges-Methode in die Datenbank eingefügt. Beispiel:

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

Eine weitere Möglichkeit, um eine neue Entität zum Kontext hinzuzufügen, besteht darin, den Status in „Added“ zu ändern. Beispiel:

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

Schließlich können Sie dem Kontext eine neue Entität hinzufügen, indem Sie diese mit einer anderen Entität verbinden, die bereits nachverfolgt wird. Das kann das Hinzufügen der neuen Entität zur Sammlungsnavigationseigenschaft einer anderen Entität oder das Festlegen einer Referenznavigationseigenschaft einer anderen Entität sein, um auf die neue Entität zu verweisen. Beispiel:

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
    blog.Posts.Add(new Post { Name = "How to Add Entities" });

    context.SaveChanges();
}

Beachten Sie, dass für alle Beispiele die neuen Entitäten ebenfalls dem Kontext hinzugefügt werden und beim nächsten Aufrufen der SaveChanges-Methode in die Datenbank eingefügt werden, wenn die hinzugefügte Entität Verweise auf andere Entitäten enthält, die noch nicht nachverfolgt werden.

Anfügen einer vorhandenen Entität an den Kontext

Wenn Sie über eine Entität verfügen, die bereits in der Datenbank vorhanden ist, die aber derzeit nicht vom Kontext nachverfolgt wird, können Sie den Kontext anweisen, die Entität mithilfe der Attach-Methode für die DbSet-Klasse nachzuverfolgen. Die Entität befindet sich im Kontext mit dem Status „Unchanged“. Beispiel:

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();
}

Beachten Sie, dass an der Datenbank keine Änderungen vorgenommen werden, wenn die SaveChanges-Methode aufgerufen wird, ohne eine andere Manipulation der angefügten Entität durchzuführen. Das liegt daran, dass sich die Entität im Zustand „Unchanged“ befindet.

Eine weitere Möglichkeit zum Anfügen einer vorhandenen Entität an den Kontext besteht darin, den Status in „Unchanged“ zu ändern. Beispiel:

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();
}

Beachten Sie, dass für beide Beispiele die neuen Entitäten auch dem Kontext im Zustand „Unchanged“ zugeordnet werden, wenn die angefügte Entität Verweise auf andere Entitäten enthält, die noch nicht nachverfolgt werden.

Anfügen einer vorhandenen, aber geänderten Entität an den Kontext

Wenn Sie über eine Entität verfügen, die bereits in der Datenbank vorhanden ist, an welcher jedoch möglicherweise Änderungen vorgenommen wurden, können Sie den Kontext anweisen, die Entität anzufügen und den Status auf „Modified“ festzulegen. Beispiel:

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();
}

Wenn Sie den Status in „Modified“ ändern, werden alle Eigenschaften der Entität als geändert markiert, und alle Eigenschaftswerte werden beim Aufrufen der SaveChanges-Methode an die Datenbank gesendet.

Beachten Sie, dass die neuen Entitäten dem Kontext im Zustand „Unchanged“ angefügt werden, wenn die angefügte Entität Verweise auf andere Entitäten enthält, die noch nicht nachverfolgt werden. Diese Entitäten werden nicht automatisch in „Modified“ geändert. Wenn Sie über mehrere Entitäten verfügen, die als „Modified“ gekennzeichnet werden müssen, sollten Sie den Status für jede dieser Entitäten einzeln festlegen.

Ändern des Status einer nachverfolgten Entität

Sie können den Status einer Entität ändern, die bereits nachverfolgt wird, indem Sie die Statuseigenschaft für den Eintrag festlegen. Beispiel:

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();
}

Beachten Sie, dass das Aufrufen der Add- oder Attach-Methode für eine bereits nachverfolgte Entität auch verwendet werden kann, um den Entitätsstatus zu ändern. Wenn Sie beispielsweise die Attach-Methode für eine Entität aufrufen, die sich derzeit im Zustand „Added“ befindet, wird der Status in „Unchanged“ geändert.

Einfügen oder Aktualisieren des Musters

Ein typisches Muster für einige Anwendungen besteht darin, eine Entität je nach dem Wert des Primärschlüssels entweder mit der Add-Methode als neu hinzuzufügen (was zu einer Datenbankeinfügung führt) oder sie mit der Attach-Methode als vorhanden anzufügen und als „Modified“ zu markieren (was zu einer Datenbankaktualisierung führt). Wenn Sie beispielsweise ganzzahlige, durch eine Datenbank generierte Primärschlüssel verwenden, ist es üblich, eine Entität mit einem Nullschlüssel als neu zu behandeln und eine Entität mit einem Schlüssel, der nicht Null ist, als vorhanden zu behandeln. Dieses Muster kann erreicht werden, indem der Entitätsstatus basierend auf einer Überprüfung des Primärschlüsselwerts festgelegt wird. Beispiel:

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

        context.SaveChanges();
    }
}

Beachten Sie, dass beim Ändern des Zustands „Modified“ alle Eigenschaften der Entität als geändert markiert werden, und alle Eigenschaftswerte werden beim Aufrufen der SaveChanges-Methode an die Datenbank gesendet.