Objektzustände und Änderungsverfolgung
LINQ to SQL-Objekte nehmen immer an einem bestimmten Zustandteil. Wenn LINQ to SQL z. B. ein neues Objekt erstellt, befindet sich dieses im Unchanged
-Zustand. Ein neues, selbst erstelltes Objekt ist dem DataContext nicht bekannt und befindet sich im Untracked
-Zustand. Nach der erfolgreichen Ausführung von SubmitChanges befinden sich alle LINQ to SQL bekannten Objekte im Unchanged
-Zustand. (Die einzige Ausnahme besteht in Objekten, die erfolgreich aus der Datenbank gelöscht wurden und sich im Deleted
-Zustand befinden, weshalb sie für die DataContext-Instanz nicht nutzbar sind.)
Objektzustände
In der folgenden Tabelle werden die möglichen Zustände für LINQ to SQL-Objekte aufgelistet.
State | Beschreibung |
---|---|
Untracked |
Ein Objekt, das nicht von LINQ to SQL nachverfolgt wird. Einige Beispiele dafür sind: - Ein Objekt, das nicht vom aktuellen DataContext abgefragt wird (z. B. ein neu erstelltes Objekt). - Ein durch Deserialisierung erstelltes Objekt - Ein Objekt, das durch einen anderen DataContext abgefragt wird. |
Unchanged |
Ein Objekt, das mit dem aktuellen DataContext abgefragt wurde und von dem nicht bekannt ist, ob es seit der Erstellung verändert wurde. |
PossiblyModified |
Ein Objekt, das an einen DataContextangehängt wurde. Weitere Informationen finden Sie unter Datenabruf und CUD-Operationen in n-schichtigen Anwendungen (LINQ to SQL). |
ToBeInserted |
Ein Objekt, das nicht vom aktuellen DataContext abgerufen wurde. Dies führt zu einem Datenbank-INSERT während SubmitChanges. |
ToBeUpdated |
Ein Objekt, von dem bekannt ist, dass es seit dem Abruf verändert wurde. Dies führt zu einem Datenbank-UPDATE während SubmitChanges. |
ToBeDeleted |
Ein zum Löschen markiertes Objekt, das zu einem Datenbank-DELETE während SubmitChanges führt. |
Deleted |
Ein Objekt, das in der Datenbank gelöscht wurde. Dieser Zustand ist endgültig und ermöglicht keine zusätzlichen Übergänge. |
Einfügen von Objekten
Sie können Inserts
mithilfe von InsertOnSubmit explizit anfordern. Alternativ dazu kann LINQ to SQL zu Inserts
führen, indem Objekte ermittelt werden, die mit einem der bekannten, zu aktualisierenden Objekte verbunden sind. Wenn Sie beispielsweise ein Untracked
-Objekt einem EntitySet<TEntity> hinzufügen oder einen EntityRef<TEntity> für ein Untracked
-Objekt festlegen, ist das Untracked
-Objekt über verfolgte Objekte im Diagramm erreichbar. Während der Verarbeitung von SubmitChanges, durchläuft LINQ to SQL die verfolgten Objekte und ermittelt alle erreichbaren vorhandenen Objekte, die nicht verfolgt werden. Solche Objekte sind Kandidaten für das Einfügen in die Datenbank.
Bei Klassen in einer Vererbungshierarchie legt InsertOnSubmit(o
) auch den Wert des als -Diskriminator bezeichneten Members fest, um den Typ des o
-Objekts anzupassen. Entspricht ein Typ dem standardmäßigen Diskriminatorwert, wird durch diese Aktion der Diskriminatorwert mit dem Standardwert überschrieben. Weitere Informationen finden Sie unter Vererbungssupport.
Wichtig
Ein der Table
hinzugefügtes Objekt befindet sich nicht im Identitäts-Cache. Der Identitäts-Cache enthält nur die Elemente, die aus der Datenbank abgerufen werden. Nach einem Aufruf von InsertOnSubmit erscheint die hinzugefügte Entität erst dann in den Abfragen für die Datenbank, wenn SubmitChanges erfolgreich abgeschlossen wurde.
Löschen von Objekten
Sie markieren ein verfolgtes Objekt o
zum Löschen, indem Sie DeleteOnSubmit(o) in der entsprechenden Table<TEntity> aufrufen. LINQ to SQL betrachtet das Entfernen eines Objekts aus einem EntitySet<TEntity> als Updatevorgang, und der entsprechende Fremdschlüsselwert wird auf NULL festgelegt. Das Ziel der Operation (o
) wird nicht aus seiner Tabelle gelöscht. cust.Orders.DeleteOnSubmit(ord)
weist beispielsweise auf ein Update hin, wenn die Beziehung zwischen cust
und ord
durch Festlegen des Fremdschlüssels ord.CustomerID
auf NULL getrennt wurde. Hierbei wird die entsprechende Zeile für ord
nicht gelöscht.
LINQ to SQL führt die folgende Verarbeitung aus, wenn ein Objekt aus der Tabelle gelöscht wird (DeleteOnSubmit):
Wenn SubmitChanges aufgerufen wird, wird eine
DELETE
-Operation für dieses Objekt ausgeführt.Die Löschung wird unabhängig davon, ob diese geladen sind, nicht an verwandte Objekte weitergeleitet. Verwandte Objekte werden vor allem nicht geladen, um die Beziehungseigenschaft zu aktualisieren.
Nach erfolgreicher Ausführung von SubmitChanges werden die Objekte auf den
Deleted
-Zustand festgelegt. Daher können Sie das Objekt oder seineid
nicht in diesem DataContext verwenden. Der interne Cache einer DataContext-Instanz eliminiert keine Objekte, die abgerufen oder neu hinzugefügt wurden, auch wenn diese in der Datenbank gelöscht wurden.
Sie können DeleteOnSubmit nur für ein Objekt aufrufen, das vom DataContext verfolgt wird. Bei einem Untracked
-Objekt müssen Sie Attach vor DeleteOnSubmit aufrufen. Der Aufruf von DeleteOnSubmit für ein Untracked
-Objekt löst eine Ausnahme aus.
Hinweis
Das Entfernen eines Objekts aus einer Tabelle weist LINQ to SQL an, einen entsprechenden SQL DELETE
-Befehl zum Zeitpunkt von SubmitChanges zu erstellen. Diese Aktion entfernt das Objekt nicht aus dem Cache und gibt das Löschen auch nicht an verwandte Objekte weiter.
Um die id
eines gelöschten Objekts freizugeben, verwenden Sie eine neue DataContext-Instanz. Zur Bereinigung verwandter Objekte können Sie die Funktion kaskadierte Löschung der Datenbank verwenden oder die verwandten Objekte manuell löschen.
Die verwandten Objekte müssen in keiner besonderen Reihenfolge gelöscht werden (im Gegensatz zur Datenbank).
Aktualisieren von Objekten
Sie können Updates
durch Überwachen der Änderungsmitteilungen erkennen. Benachrichtigungen werden durch das PropertyChanging-Ereignis in Eigenschaften-Settern bereitgestellt. Wird LINQ to SQL über die erste Änderung an einem Objekt benachrichtigt, wird eine Kopie dieses Objekts erstellt, und das Objekt gilt als Kandidat zur Erzeugung einer Update
-Anweisung.
Bei Objekten, die INotifyPropertyChanging nicht implementieren, behält LINQ to SQL eine Kopie der Werte bei, die die Objekte bei der ersten Materialisierung aufwiesen. Wenn Sie SubmitChanges aufrufen, vergleicht LINQ to SQL die aktuellen und ursprünglichen Werte, um zu entscheiden, ob das Objekt geändert wurde.
Bei Updates von Beziehungen gilt der Verweis vom unter- zum übergeordneten Element (der Verweis, der dem Fremdschlüssel entspricht) als Autorität. Der Verweis in die umgekehrte Richtung (d. h. vom übergeordneten zum untergeordneten Element) ist optional. Beziehungsklassen (EntitySet<TEntity> und EntityRef<TEntity>) stellen die Konsistenz bidirektionaler Verweise für 1:n-Beziehungen und 1:1-Beziehungen sicher. Verwendet das Objektmodel EntitySet<TEntity> oder EntityRef<TEntity> nicht und ist ein umgekehrter Verweis vorhanden, ist es Ihre Aufgabe, diesen beim Update der Beziehung mit dem vorwärts gerichteten Verweis konsistent zu halten.
Wenn Sie den erforderlichen Verweis und den entsprechenden Fremdschlüssel aktualisieren, müssen Sie deren Übereinstimmung sicherstellen. Eine InvalidOperationException-Ausnahme wird ausgelöst, wenn die beiden Elemente zum Zeitpunkt des Aufrufs von SubmitChanges nicht synchron sind. Obwohl die Werte von Fremdschlüsseln für ein Update der zugrunde liegenden Zeile ausreichen, müssen Sie die Referenz ändern, um die Konnektivität des Objektgraphen und die bidirektionale Konsistenz von Beziehungen zu erhalten.