Getrennte EntitätenDisconnected entities

Eine Instanz von ' DbContext ' verfolgt automatisch Entitäten, die aus der Datenbank zurückgegeben.A DbContext instance will automatically track entities returned from the database. Änderungen an diesen Entitäten werden dann erkannt werden, wenn SaveChanges aufgerufen und die Datenbank aktualisiert werden, wenn erforderlich.Changes made to these entities will then be detected when SaveChanges is called and the database will be updated as needed. Finden Sie unter grundlegende speichern und verknüpften Daten für Details.See Basic Save and Related Data for details.

Allerdings sind manchmal Entitäten abgefragt werden mehrere Instanzen von Kontext verwenden, und klicken Sie dann gespeichert mit einer anderen Instanz.However, sometimes entities are queried using one context instance and then saved using a different instance. Dies geschieht häufig in "getrennt" Szenarien, z. B. eine Webanwendung, in denen die Entitäten werden abgefragt, an den Client gesendet, geändert, zurück an den Server in einer Anforderung gesendet und anschließend gespeichert.This often happens in "disconnected" scenarios such as a web application where the entities are queried, sent to the client, modified, sent back to the server in a request, and then saved. In diesem Fall der zweiten Kontext Instanz muss wissen, ob die Entitäten nicht vertraut sind (sollte nun eingefügt sein), oder vorhandene (sollte aktualisiert werden).In this case, the second context instance needs to know whether the entities are new (should be inserted) or existing (should be updated).

Tipp

Sie können anzeigen, dass dieser Artikel Beispiel auf GitHub.You can view this article's sample on GitHub.

Identifizieren neue EntitätenIdentifying new entities

Client identifiziert neue EntitätenClient identifies new entities

Der einfachste Fall zu behandeln ist, wenn der Client dem Server informiert, ob die Entität neuen oder vorhandenen ist.The simplest case to deal with is when the client informs the server whether the entity is new or existing. Beispielsweise unterscheidet sich häufig die Anforderung an eine neue Entität einfügen aus der Anforderung zum Aktualisieren einer vorhandenen Entität.For example, often the request to insert a new entity is different from the request to update an existing entity.

Der übrige Teil dieses Abschnitts behandelt die Fälle, in denen es erforderlich, auf andere Weise zu ermitteln, ob zum Einfügen oder aktualisieren.The remainder of this section covers the cases where it necessary to determine in some other way whether to insert or update.

Mit automatisch generierten SchlüsselnWith auto-generated keys

Der Wert von einem automatisch generierten Schlüssel kann häufig verwendet werden, um zu bestimmen, ob eine Entität eingefügt oder aktualisiert werden muss.The value of an automatically generated key can often be used to determine whether an entity needs to be inserted or updated. Wenn der Schlüssel, nicht hat festgelegt (d. h. es immer noch den CLR-Standardwert von Null, 0 (null), usw.), wurde, wird die Entität neue muss und Einfügen benötigt.If the key has not been set (i.e. it still has the CLR default value of null, zero, etc.), then the entity must be new and needs inserting. Andererseits, wenn der Schlüssel-Wert festgelegt wurde, dann muss wurden bereits zuvor gespeichert und ist jetzt ein Update erforderlich.On the other hand, if the key value has been set, then it must have already been previously saved and now needs updating. Das heißt, wenn der Schlüssel einen Wert hat, klicken Sie dann Entität abgefragt wurde, an den Client gesendet und hat jetzt zurückkehren, um aktualisiert werden.In other words, if the key has a value, then entity was queried, sent to the client, and has now come back to be updated.

Es ist einfach, eine Festlegung Schlüssel überprüfen, wenn der Entitätstyp bekannt ist:It is easy to check for an unset key when the entity type is known:

public static bool IsItNew(Blog blog) 
    => blog.BlogId == 0;

EF hat jedoch auch eine integrierten Möglichkeit hierzu für jede Entitätstyp und der Typ des Schlüssels:However, EF also has a built-in way to do this for any entity type and key type:

public static bool IsItNew(DbContext context, object entity) 
    => !context.Entry(entity).IsKeySet;

Tipp

Schlüssel werden als Entitäten vom Kontext, nachverfolgt werden festgelegt, selbst wenn die Entität im Zustand ' Added ' befindet.Keys are set as soon as entities are tracked by the context, even if the entity is in the Added state. Dies ist hilfreich beim Durchlaufen von Entitäten und entscheiden Vorgehensweise mit einzelnen, z. B. bei Verwendung der TrackGraph-API in einem Diagramm.This helps when traversing a graph of entities and deciding what to do with each, such as when using the TrackGraph API. Der Schlüssel-Wert sollte nur verwendet werden, auf die Weise, die hier gezeigten vor wird jeder Aufruf zum Nachverfolgen der Entität.The key value should only be used in the way shown here before any call is made to track the entity.

Mit anderen SchlüsselnWith other keys

Ein anderen Mechanismus ist für neue Entitäten Identität erforderlich, wenn Schlüsselwerte nicht automatisch generiert werden.Some other mechanism is needed to identity new entities when key values are not generated automatically. Es gibt zwei allgemeine Vorgehensweisen beim dies:There are two general approaches to this:

  • Abfrage für die EntitätQuery for the entity
  • Übergeben Sie ein Flag vom clientPass a flag from the client

Für die Entität eine Abfrage nur verwenden Sie die Find-Methode:To query for the entity, just use the Find method:

public static bool IsItNew(BloggingContext context, Blog blog)
    => context.Blogs.Find(blog.BlogId) == null;

Es ist nicht Gegenstand dieses Dokuments, um den vollständigen Code für die Übergabe eines Flags von einem Client anzuzeigen.It is beyond the scope of this document to show the full code for passing a flag from a client. In einer Web-app bedeutet dies normalerweise, die verschiedene Anforderungen für unterschiedliche Aktionen, oder ein Zustand, der in der Anforderung übergeben, und extrahieren es im Controller.In a web app, it usually means making different requests for different actions, or passing some state in the request then extracting it in the controller.

Speichern die einzelne EntitätenSaving single entities

Wenn es bekannt ist, unabhängig davon, ob eine INSERT- oder Update ist erforderlich, und klicken Sie dann hinzufügen oder aktualisieren ordnungsgemäß verwendet werden kann:If it is known whether or not an insert or update is needed, then either Add or Update can be used appropriately:

public static void Insert(DbContext context, object entity)
{
    context.Add(entity);
    context.SaveChanges();
}

public static void Update(DbContext context, object entity)
{
    context.Update(entity);
    context.SaveChanges();
}

Jedoch, wenn die Entität automatisch generierten Schlüsselwerte verwendet wird, kann dann die Update-Methode für beide Fälle verwendet werden:However, if the entity uses auto-generated key values, then the Update method can be used for both cases:

public static void InsertOrUpdate(DbContext context, object entity)
{
    context.Update(entity);
    context.SaveChanges();
}

Die Update-Methode markiert normalerweise die Entität für das Update nicht einfügen.The Update method normally marks the entity for update, not insert. Wenn die Entität einen automatisch generierten Schlüssel hat, und kein Schlüsselwert festgelegt wurde, und klicken Sie dann die Entität für stattdessen automatisch markiert ist allerdings fügen Sie zu können ein.However, if the entity has a auto-generated key, and no key value has been set, then the entity is instead automatically marked for insert.

Tipp

Dieses Verhalten wurde in der EF Core 2.0 eingeführt.This behavior was introduced in EF Core 2.0. Bei früheren Versionen ist es immer erforderlich, um explizit anzugeben, hinzufügen oder aktualisieren.For earlier releases it is always necessary to explicitly choose either Add or Update.

Wenn die Entität wird nicht automatisch generierten Schlüssel verwenden, die Anwendung muss entscheiden Sie, ob die Entität eingefügt oder aktualisiert werden: Z. B.:If the entity is not using auto-generated keys, then the application must decide whether the entity should be inserted or updated: For example:

public static void InsertOrUpdate(BloggingContext context, Blog blog)
{
    var existingBlog = context.Blogs.Find(blog.BlogId);
    if (existingBlog == null)
    {
        context.Add(blog);
    }
    else
    {
        context.Entry(existingBlog).CurrentValues.SetValues(blog);
    }

    context.SaveChanges();
}

Bei den folgenden Schritten werden:The steps here are:

  • Wenn suchen gibt null ist, und klicken Sie dann die Datenbank im Blog mit dieser ID bereits enthält, damit wir rufen hinzufügen markieren Sie es zum Einfügen.If Find returns null, then the database doesn't already contain the blog with this ID, so we call Add mark it for insertion.
  • Wenn suchen eine Entität zurückgibt, klicken sie in der Datenbank vorhanden ist und der Kontext verfolgt nun der vorhandenen EntitätIf Find returns an entity, then it exists in the database and the context is now tracking the existing entity
    • Klicken Sie dann verwenden wir SetValues, um die Werte für alle Eigenschaften für diese Entität, mit denen festgelegt wird, die vom Client stammen.We then use SetValues to set the values for all properties on this entity to those that came from the client.
    • Der Aufruf SetValues werden in der Entität aktualisiert werden, nach Bedarf gekennzeichnet.The SetValues call will mark the entity to be updated as needed.

Tipp

SetValues kennzeichnet nur, wie die Eigenschaften geändert werden, die über unterschiedliche Werte in die nachverfolgte Entität verfügen.SetValues will only mark as modified the properties that have different values to those in the tracked entity. Dies bedeutet, dass das Update gesendet werden, wird nur die Spalten, die tatsächlich geändert wurden aktualisiert.This means that when the update is sent, only those columns that have actually changed will be updated. (Und wenn nichts geändert wurde, wird kein Update auf allen gesendet,.)(And if nothing has changed, then no update will be sent at all.)

Arbeiten mit DiagrammenWorking with graphs

Alle neuen Eigenschaft bzw. alle vorhandenen EntitätenAll new/all existing entities

Ein Beispiel für das Arbeiten mit Diagrammen wird einfügen oder aktualisieren ein Blogs zusammen mit ihrer Auflistung von zugehörigen Beiträge.An example of working with graphs is inserting or updating a blog together with its collection of associated posts. Wenn alle Entitäten im Diagramm eingefügt werden soll, oder alle aktualisiert werden soll, ist der Prozess identisch für einzelne Entitäten wie oben beschrieben aus.If all the entities in the graph should be inserted, or all should be updated, then the process is the same as described above for single entities. Angenommen, ein Diagramm der Blogs und Beiträge, die wie folgt erstellt:For example, a graph of blogs and posts created like this:

var blog = new Blog
{
    Url = "http://sample.com",
    Posts = new List<Post>
    {
        new Post {Title = "Post 1"},
        new Post {Title = "Post 2"},
    }
};

können wie folgt eingefügt werden:can be inserted like this:

public static void InsertGraph(DbContext context, object rootEntity)
{
    context.Add(rootEntity);
    context.SaveChanges();
}

Der Aufruf von Add werden im Blog und alle Beiträge einzufügenden gekennzeichnet.The call to Add will mark the blog and all the posts to be inserted.

Ebenso, wenn alle Entitäten in einem Diagramm aktualisiert werden müssen, kann dann Update verwendet werden:Likewise, if all the entities in a graph need to be updated, then Update can be used:

public static void UpdateGraph(DbContext context, object rootEntity)
{
    context.Update(rootEntity);
    context.SaveChanges();
}

Im Blog und alle ihre Beiträge werden gekennzeichnet werden, um aktualisiert werden.The blog and all its posts will be marked to be updated.

Mischung neue und vorhandene EntitätenMix of new and existing entities

Mit automatisch generierten Schlüssel kann Update erneut für einfügungen und Updates, verwendet werden, selbst wenn das Diagramm enthält eine Mischung aus Entitäten, die eingefügt werden müssen, auch solche, die aktualisiert werden müssen:With auto-generated keys, Update can again be used for both inserts and updates, even if the graph contains a mix of entities that require inserting and those that require updating:

public static void InsertOrUpdateGraph(DbContext context, object rootEntity)
{
    context.Update(rootEntity);
    context.SaveChanges();
}

Update kennzeichnet jede Entität im Diagramm, Blog oder Post zum Einfügen, wenn sie einen Satz Schlüsselwert keinen während alle anderen Entitäten für Update markiert sind.Update will mark any entity in the graph, blog or post, for insertion if it does not have a key value set, while all other entities are marked for update.

Wie vor, bei der automatisch generierten Schlüssel nicht mit einer Abfrage und einige Verarbeitungsschritte verwendet werden können:As before, when not using auto-generated keys, a query and some processing can be used:

public static void InsertOrUpdateGraph(BloggingContext context, Blog blog)
{
    var existingBlog = context.Blogs
        .Include(b => b.Posts)
        .FirstOrDefault(b => b.BlogId == blog.BlogId);

    if (existingBlog == null)
    {
        context.Add(blog);
    }
    else
    {
        context.Entry(existingBlog).CurrentValues.SetValues(blog);
        foreach (var post in blog.Posts)
        {
            var existingPost = existingBlog.Posts
                .FirstOrDefault(p => p.PostId == post.PostId);

            if (existingPost == null)
            {
                existingBlog.Posts.Add(post);
            }
            else
            {
                context.Entry(existingPost).CurrentValues.SetValues(post);
            }
        }
    }

    context.SaveChanges();
}

Behandlung von LöschvorgängenHandling deletes

Delete aufspüren zu kann, da behandeln das Fehlen einer Entität bedeutet häufig, dass sie gelöscht werden soll.Delete can be tricky to handle since often the absence of an entity means that it should be deleted. Eine Möglichkeit für den Umgang mit Dies ist die Verwendung von "vorläufige Löschvorgänge", so, dass die Entität markiert ist, als gelöscht, statt Sie tatsächlich gelöscht werden.One way to deal with this is to use "soft deletes" such that the entity is marked as deleted rather than actually being deleted. Löscht wird dann der Updates identisch.Deletes then becomes the same as updates. Vorläufige Löschvorgänge können implementiert werden, sich mit Abfragen Filter.Soft deletes can be implemented in using query filters.

Für "true" löscht wird ein allgemeines Muster um eine Erweiterung des Abfragemusters für eine durchführen, was im Wesentlichen ein Diagramm Diff. Zum Beispiel:For true deletes, a common pattern is to use an extension of the query pattern to perform what is essentially a graph diff. For example:

public static void InsertUpdateOrDeleteGraph(BloggingContext context, Blog blog)
{
    var existingBlog = context.Blogs
        .Include(b => b.Posts)
        .FirstOrDefault(b => b.BlogId == blog.BlogId);

    if (existingBlog == null)
    {
        context.Add(blog);
    }
    else
    {
        context.Entry(existingBlog).CurrentValues.SetValues(blog);
        foreach (var post in blog.Posts)
        {
            var existingPost = existingBlog.Posts
                .FirstOrDefault(p => p.PostId == post.PostId);

            if (existingPost == null)
            {
                existingBlog.Posts.Add(post);
            }
            else
            {
                context.Entry(existingPost).CurrentValues.SetValues(post);
            }
        }

        foreach (var post in existingBlog.Posts)
        {
            if (!blog.Posts.Any(p => p.PostId == post.PostId))
            {
                context.Remove(post);
            }
        }
    }

    context.SaveChanges();
}

TrackGraphTrackGraph

Intern, Add-, Anfügen und Update verwenden Graph-Durchlauf mit einem Feststellung für jede Entität, gibt an, ob er als hinzugefügt (insert), "geändert" (zu aktualisieren), markiert werden soll Unchanged (keine), oder gelöschte (zu löschen).Internally, Add, Attach, and Update use graph-traversal with a determination made for each entity as to whether it should be marked as Added (to insert), Modified (to update), Unchanged (do nothing), or Deleted (to delete). Dieser Mechanismus wird über die TrackGraph-API verfügbar gemacht.This mechanism is exposed via the TrackGraph API. Nehmen wir beispielsweise an, sendet der Client wieder Entitäten in einem Diagramm wird einige Kennzeichen für jede Entität, der angibt, wie sie behandelt werden sollen.For example, let's assume that when the client sends back a graph of entities it sets some flag on each entity indicating how it should be handled. TrackGraph kann dann verwendet werden, um dieses Flag zu verarbeiten:TrackGraph can then be used to process this flag:

public static void SaveAnnotatedGraph(DbContext context, object rootEntity)
{
    context.ChangeTracker.TrackGraph(
        rootEntity,
        n =>
        {
            var entity = (EntityBase)n.Entry.Entity;
            n.Entry.State = entity.IsNew
                ? EntityState.Added
                : entity.IsChanged
                    ? EntityState.Modified
                    : entity.IsDeleted
                        ? EntityState.Deleted
                        : EntityState.Unchanged;
        });

    context.SaveChanges();
}

Die Flags werden nur als Teil der Entität aus Gründen der Einfachheit der im Beispiel angezeigt.The flags are only shown as part of the entity for simplicity of the example. In der Regel würden die Flags Teil einer DTO oder einem anderen Status in der Anforderung enthalten sein.Typically the flags would be part of a DTO or some other state included in the request.