2017-06-12 2 views
2

Ich verwende AutoMapper und versuche AutoMapper.Collection.EntityFramework, speziell die Persist<T> Methode.AutoMapper.Collection.EntityFramework verursacht InvalidOperationException nach Persist.InsertOrUpdate

Meine "Quelle" ist ein ziemlich großes Objektdiagramm, das (von AutoMapper) in einige EntityFramework Entities konvertiert wurde. Die übergeordnete Entität heißt Log. Das Anwesen 'Id' Teil der:

In meinem experimentellen Test, ich folgendes:

var mapper = collectionConfig.CreateMapper(); 
var persistence = dbContext.Logs.Persist(mapper); 
var testLog = logs.First(); // "logs" is the output of an AutoMapper.Map of a collection. 
persistence.InsertOrUpdate<Log>(testLog); 

Assert.IsTrue(dbContext.ChangeTracker.HasChanges()); 

Was passiert, ist eine Ausnahme bei der ChangeTracker.HasChanges Aufruf:

System.InvalidOperationException Objekt Schlüsselinformationen und kann nicht geändert werden.

die Stapelüberwachung ist:

System.Data.Entity.Core.Objects.EntityEntry.DetectChangesInProperty (Int32 ordinal, Boolean detectOnlyComplexProperties, Boolean DetectOnly)
bei System.Data.Entity .Core.Objects.EntityEntry.DetectChangesInProperties (Boolean detectOnlyComplexProperties) bei System.Data.Entity.Core.Objects.ObjectStateManager.DetectChangesInScalarAndComplexProperties (IList`1 Einträge) bei System.Data.Entity.Core.Objects.ObjectStateManager.DetectChanges()
bei System.Data.Entity.Core.Objects.ObjectContext.DetectChanges() bei System.Data.Entity.Internal.InternalContext.DetectChanges (Boolean Kraft) bei System.Data.Entity.Infrastructure.DbChangeTracker.HasChanges()

Dies ist eine ziemlich bekannte und gut dokumentierte Ausnahme: es passiert, wenn Sie ein vorhandenes EntityFramework Entitätsobjekt haben und versuchen, das zu ändern Wert eines seiner primären Schlüsseleigenschaftenfelder.

Aber ich mache das nirgendwo.

Ich habe nie einen Id Wert irgendwo in meinem Code festgelegt. (Der Wert für die Id Eigenschaft kommt von woanders und wird von AutoMapper festgelegt, wenn die Liste der Log Objekte erstellt wird. Aufgrund der Art der Daten bin ich ziemlich sicher, dass ein Eintrag für das testLog Objekt bereits in der Datenbank vorhanden ist.

)

ich habe in der Lage gewesen, durch AutoMapper ganze Sammlungen von Log Einträgen, erstellt zu speichern, auf die Datenbank, durch EF, so dass ich glaube nicht, meine Log Einheiten oder das Objektgraph das Problem. Ich denke, es ist etwas, AutoMapper.Collection.EntityFramework tut irgendwie.

Ich habe die Persist-Methode mit einer anderen, einfacheren Entität mit viel weniger untergeordneten Entitäten versucht und hatte dieses Problem nicht. Aber ich kann aus diesem Fehler nicht einmal erkennen, welches Objekt im Graphen den vermeintlich geänderten Wert Id hat: Die Hälfte der Objekte in diesem Objektgraph hat einen Primärschlüssel namens Id.

Ich kann bestätigen, dass der tatsächliche Wert von testLog.Id wird nicht durch die InsertOrUpdate geändert. Aber meine Versuche, eine Entry<Log> für testLog zu untersuchen oder sogar dbContext.Logs.Local zu betrachten, verursachen, dass die gleiche Ausnahme ausgelöst wird.

Also: hat jemand eine Idee, warum das passiert?

Antwort

0

Dank Tyler Carlson von AutoMapper.Collection, habe ich eine Antwort.

persistence.InsertOrUpdate<Log>(testLog); 

Das Problem von testLog stammte bereits vom Typ sein Log, die die gleiche Art ist, ich bin in EntityFramework verwenden. Wie Tyler sagte:

Automapper unterstützt keine Zuordnung zu sich selbst, da es so viele Probleme verursacht. [...]
Was Sie tun sollten, ist der dto in den Persist-Aufruf übergeben, nicht die Entität, die zugeordnet ist. Das Mapping wird in dem InsertOrUpdate-Aufruf auftreten.

Wir entdeckten auch, dass, wenn Ihre Entity und Dto Objekte eine gemeinsame Basisklasse teilen, und dass Basisklasse enthält die Definition der Schlüsselfelder, wird dies auch geschehen.

Also in meiner Situation, wo meine Entity und Dto 95% der gleichen Felder enthalten ist, von einer gemeinsamen Basisklasse abgeleitet, hatte ich das Id Eigentum zu nehmen, dass der Primärschlüssel aus der Basisklasse war, und definiere es getrennt in den zwei Klassen. Das stellte sicher, dass, während die Eigenschaften die gleichen Namen hatten, sie in keiner Hinsicht die gleiche Eigenschaft von einem Gesichtspunkt waren.

Wenn Sie neugierig auf die Details sind, finden Sie hier die Diskussion: AutoMapper.Collection Issue 40.

Verwandte Themen