2016-03-20 21 views
0

Ich habe ein Projekt, das Entity Framework ausgiebig verwendet. Und alles funktioniert gut.Entity Framework aktualisiert keine vorhandene verbundene Entität

Allerdings gibt es ein Update, das ich versuche zu machen und es wird nicht aktualisiert, noch wird ein Fehler ausgelöst.

Der grundlegende Prozess besteht darin, dass ich eine vorhandene Entität nehme, mit ihr arbeite, um einen neuen (und anderen Typ) Entity zu erstellen. Die neue Entität spart gut, aber die bestehende nicht.

Normalerweise, wenn ich dies festgestellt habe, bedeutet dies, dass die Entität nicht an den Kontext gebunden ist. Wie auch immer, es ist, und ich habe versucht, es wieder anzuhängen sowie "Hinzufügen", aber ich hatte kein Glück.

 if (fileRowEntity != null) 
     { 
      this.Context.FileRowEntities.Attach(fileRowEntity); 
      fileRowEntity.FileRowStatusId = (int)FileRowStatus.Converted; 
      fileRowEntity.EdiDocument = ediDocument; 
     } 

     ediDocument.InsertedDate = DateTime.Now; 
     ediDocument.EdiDocumentGuid = Guid.NewGuid(); 
     ediDocument.DocumentMetatdata = null; 
     this.Context.EdiDocuments.Add(ediDocument); 
     var count = this.Context.SaveChanges(); 

Die ediDocument wird gespeichert, aber die fileRowEntity nicht gespeichert.

Ich reiße mir die Haare aus, um das herauszufinden. Ich habe versucht, auf der fileRowEntity eine zweite explizite zu speichern, aber es kommt wieder mit Null Änderungen gespeichert:

 if (fileRowEntity != null) 
     { 
      fileRowEntity.EdiDocumentId = ediDocument.EdiDocumentId; 
      fileRowEntity.Column100 = "X"; 
      this.Context.FileRowEntities.Attach(fileRowEntity); 
      count = this.Context.SaveChanges(); 
     } 

count ist immer Null, und die Datenbank wird nicht aktualisiert.

Ich weiß nicht, was noch zu versuchen, dies zu debuggen.

+0

Wenn Sie eine Entity anhängen, wird sie nicht als geändert markiert ... haben Sie versucht, 'Context.Entry (fileRowEntity) .State = EntityState.Modified;'? (Sie müssen es nicht anhängen, das wird die Entity anhängen, wenn es auch losgelöst ist). Wenn die Entität kein Proxy ist und/oder zuvor geladen wurde, weiß EF nicht, dass Änderungen daran vorgenommen wurden, es sei denn, Sie teilen dies mit, sodass keine Aktualisierungen vorgenommen werden. Es sollte explizit als "Modified" markiert werden. – Jcl

+0

Danke. Ja, das macht die Speicherung tatsächlich möglich. Bedeutet dies, dass sich die Entität tatsächlich nicht im selben Kontext befand? Soweit ich das beurteilen kann, wird der gleiche Entity Manager verwendet, um die Entitäten als speichern sie abzurufen. –

+0

Wenn eine Entität aus der Datenbank geladen wird, werden ihre ursprünglichen Werte (wie sie abgerufen wurden) im Kontext gespeichert (Sie können sie in "Context.Entry (entity) .OriginalValues" überprüfen), wenn dbcontext dies überprüft ändert (durch Aufrufen von 'DetectChanges'), speichert es die neuen Werte (Sie können sie in' Context.Entry (entity) .CurrentValues' überprüfen), und wenn eine davon geändert wird, wird beim Speichern der Änderungen ein 'UPDATE' generiert . Wenn also die ursprüngliche Entität durch denselben Kontext aus der Datenbank abgerufen wurde, dann sollte sie die Änderungen erkennen und die Änderungen speichern. – Jcl

Antwort

2

Das Anhängen einer Entität an einen Kontext markiert diese nicht als geändert.

In Ihrem Fall ist die Annahme, dass die Kontextinstanz, in der Sie SaveChanges() aufrufen, nicht das gleiche ist, das das Objekt fileRowEntity abgerufen hat, so dass es nicht weiß, dass es geändert wurde (oder was geändert wurde).

Wenn ein DbContext ein Objekt aus dem Speicher abruft, es speichert eine Kopie der ursprünglichen Werte (es sei denn, Sie AsNoTracking() auf dieser Abfrage verwendet wird), und immer dann, wenn es erkennt, Änderungen durch einen Aufruf DetectChanges(), die Sie explizit machen, aber die normale DbContext Implementierung wird es an vielen Punkten selbst aufrufen), es speichert die neuen Objektwerte. Wenn es Unterschiede zwischen diesen gibt, aktualisiert der nächste Aufruf von SaveChanges die Entität in der Filiale/Datenbank.

Wenn Sie ein Objekt anhängen aber markieren Sie es nicht so verändert, es weiß nichts geändert hat, so dass Sie explizit als die Entität geändert markieren können:

Context.Entry(fileRowEntity).State = EntityState.Modified; Verwendung sollte EF sagen, dass Ihr Unternehmen war geändert, und es wird den Update-Befehl generieren, wenn Sie SaveChanges() für die gesamte Entität aufrufen (es sendet alle Feldwerte in der UPDATE SQL). Beachten Sie, dass dadurch auch die Entität angehängt wird, wenn sie nicht an den Kontext angehängt wurde (es muss nicht angehängt und dann der Status festgelegt werden).

Sie können auch nur die Eigenschaften markieren, die geändert wurden (oder ändern Sie die Entität OriginalValues), auf diese Weise wird Ihre Abfrage optimiert (es werden nur die Felder aktualisiert, die sich tatsächlich geändert haben).Es ist ein bisschen mühsam, diese Änderungen selbst zu verfolgen, aber wenn Sie diese zusätzliche Optimierung benötigen, ist es einen Versuch wert (persönlich, es sei denn, es gibt eine kritische Last auf dem Datenbankserver und jedes Bit zählt, würde ich nicht tun, aber Ihre Wahl)

1

es gibt einen zweiten Grund für das oben beschriebene Verhalten: Dieser Code wird die Änderungsverfolgung deaktivieren:

Context.Configuration.AutoDetectChangesEnabled = false; 

Nachdem ich diese gefunden im Konstruktor festgelegt worden war, und entfernt es, alles funktioniert wie erwartet.

+1

Das stimmt. Die Standardeinstellung ist automatisch und ich habe nicht an die Möglichkeit gedacht, dass Sie sie hätte deaktivieren können. Wenn Sie nach dem Aktivieren der automatischen Änderungserkennung ein langsames Verhalten bemerken, können Sie DetectChanges explizit aufrufen. EF neigt dazu, mehr Erkennungen zu machen als nötig :-) – Jcl

+0

Guter Punkt. Nochmals, danke, ich konnte das nicht herausfinden :) –

Verwandte Themen