Laden...

Entity Framework - verhindern von Zwischenspeicherung/Tracking ohne direkten Zugriff auf den Context

Erstellt von Sera vor 12 Jahren Letzter Beitrag vor 12 Jahren 1.908 Views
S
Sera Themenstarter:in
285 Beiträge seit 2005
vor 12 Jahren
Entity Framework - verhindern von Zwischenspeicherung/Tracking ohne direkten Zugriff auf den Context

verwendetes Datenbanksystem: <SQL Server 2008>

Hallo,

Ich beobachte derzeit ein merkwürdiges Verhalten des EF 4.0.

Folgendes Problem:


Customer customer = new Customer();
customer.Name = "Maier"

City city = new City();
city = GetCityEntity("München");

customer.City = city; // Die City Navigation Property greift wohl irgendwie auf den Context zu

context.SaveChanges();

Und tatsächlich wird dieses Objekt in der DB abgelegt, ohne AddObject des Contexts selbst zu benutzen. Ist das nicht merkwürdig? Kann man dieses Verhalten unterbinden? Ich arbeite übrigens mit POCO. Proxy oder Tracking zu deaktivieren bringt nichts. Normalerweise wird der unten angezeigte Code aus einer externen DLL aufgerufen. Nur die POCO Klassen sind für diese sichtbar, wo der Customer als Parameter an die DAL DLL übergeben wird.

2 identische Datensätze werden mit diesem Code angelegt:


Customer customer = new Customer();
customer.Name = "Maier"

City city = new City();
city = GetCityEntity("München");

customer.City = city; // Die City Navigation Property greift wohl irgendwie auf den Context zu

context.Customers.AddObject(customer); // Doppelter Maier

context.SaveChanges();

1.552 Beiträge seit 2010
vor 12 Jahren

Halla Sera,

Ist das nicht merkwürdig? Kann man dieses Verhalten unterbinden?

Nein kann man nicht.

Du kannst aber über EntityState abprüfen ob das city Object schon am ObjectContext hängt aber noch nicht gespeichert wurde (Attached) oder noch nicht dran hängt (Detached).

2 identische Datensätze werden mit diesem Code angelegt:

Mit diesem Problem wurde sicher jeder der Erfahrungen mit dem EF machte konfrontiert. Aber mit oben genannten wird dies unterbunden.

Gruß
Michael

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

6.911 Beiträge seit 2009
vor 12 Jahren

Hallo Sera,

Zitat von: Add/Attach and Entity States
Finally, you can add a new entity to the context by hooking it up to another entity that is already being tracked. This could be by adding the new entity to the collection navigation property of another entity or by setting a reference navigation property of another entity to point to the new entity.

Ist zwar aus EF4.1 zitiert gilt aber für EF4.0 genauso da ersteres darauf basiert. Der fette-Teil trifft bei dir zu.

Das Verhalten macht mMn durchaus Sinn denn somit wird bei SaveChanges das Objektmodell mit der DB synchron gehalten.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

849 Beiträge seit 2006
vor 12 Jahren

By the way.. warum erzeugst du erst ein neues Object vom Typ City, und ersetzt es dann durch eins aus der Datenbank? Da liegt der Hase im Pfeffer. Dein Context kennt deine City.. und sobald Du deinem Customer die City zuweist, kennt er auch deinen Customer.

Kannst im Poco Code nachschauen. Da gibts bestimmt ne methode FixupCity oder ähnlich, die Deiner City auch den Customer zu der Liste der möglichen Customer in München hinzufügt.. Und FUPPP Big Brother is Watching YOU 😉

edit: was gfoidl natürlich schon in seinem Zitat stehen hat.. Mist man sollte genauer hinschauen.. sorry

S
Sera Themenstarter:in
285 Beiträge seit 2005
vor 12 Jahren

@gfoidl

Wollte gerade ein Kommentar von dir aus einem anderen Thread zitieren (POCO und Unabhängigkeit). Da es sich ja um POCO's handelt, sollte dieses Verhalten für diese nicht zutreffen. Speziell dann nicht, wenn diese POCO's in einer externen DLL benutzt werden, die vorab den Graphen aufbauen und zur weiteren Bearbeitung an die DAL übergeben. Eine Referenz zu setzen (fetter Teil) funktioniert nur bequem, wenn tatsächlich zuvor einmal gespeichert wurde.

EDIT: wenn ich xxMUROxx's Tipp verwende ist das natürlich kein Problem, nur wird es unübersichtlich.

@unconnected

Die Methode gibt entweder eine neue City zurück oder eine bereits in der DB angelegte, ich verwende nicht die ID als Rückgabeparameter, wenn ich direkt via Property die Entity Referenz setzen kann. Da ist es egal ob ich ein neues Objekt anlege, da "city" dann im Heap neu referenziert wird durch das zurückgegebene Objekt der Methode.

Übrigens, ja es stimmt, daß Context "München" kennt, aber nur wenn "München" nicht neu angelegt wurde. Wenn München neu angelegt wird, dann überprüft die Methode im DAL, ob München bereits vorhanden ist. Der hier von mir gezeigte Code funktioniert in einer externen DLL nicht, da dort nur die POCO's angezeigt werden. GetCityEntity ist private im DAL verankert. Nicht nur der Maier wird 2x angelegt, sondern auch München, wenn ich nicht neu referenziere. Kranke Logik.

S
Sera Themenstarter:in
285 Beiträge seit 2005
vor 12 Jahren

Ist gelöst, danke an alle.

Der Weg mit dem State check bzw. mit einem Reset des ObjectContexts funktioniert zwar, jedoch unnötige Coderedundanz durch die DAL Methode, die alle Properties kopiert.

Habe den redundanten Code gelöscht, und die Methode beinhaltet, neben dem Check der vorhandenen Properties, eigentlich nur noch mehr die SaveChanges() Methode. Keine Ahnung, ich sage es ist Geschmackssache.

16.835 Beiträge seit 2008
vor 12 Jahren

Da es sich ja um POCO's handelt, sollte dieses Verhalten für diese nicht zutreffen.

Ich arbeite Applikationsbedingt (Web) nur mit POCOs und kann bestätigen, dass dieses Verhalten absolut "normal" ist - auch bei POCOs.
Man muss es halt wissen.

6.911 Beiträge seit 2009
vor 12 Jahren

Hallo,

noch als Ergänzung: POCOs haben als Klasse keine Abhängigkeit zum EF oder sonst was. Das heißt aber nicht dass die Objekte der POCO-Klasse nicht vom EF verfolgt werden können - zB indem ein Snapshot beim Laden erstellt wird und gegen diesen wird verglichen.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

S
Sera Themenstarter:in
285 Beiträge seit 2005
vor 12 Jahren

Zitat von: Add/Attach and Entity States
Finally, you can add a new entity to the context by hooking it up to another entity that is already being tracked. This could be by adding the new entity to the collection navigation property of another entity or by setting a reference navigation property of another entity to point to the new entity. Ist zwar aus EF4.1 zitiert gilt aber für EF4.0 genauso da ersteres darauf basiert. Der fette-Teil trifft bei dir zu.

Das Verhalten macht mMn durchaus Sinn denn somit wird bei SaveChanges das Objektmodell mit der DB synchron gehalten.

Danke für den Versionshinweis. DbContext ist genau das, was ich gesucht habe und dieses Verhalten auch unterbindet. Mittlerweile benutze ich 3 verschiedene DLL's (EF Standard, POCO, DbContext), um für verschiedene Szenarien die passende Funktionen zu benutzen.