Ich habe in einem Daten-Model die Entity "Location" mit folgender Methode innerhalb des zugehörigen Repositories:
public Location GetLocation(int locationId)
{
Location location = Context.Locations.First(l => l.Id == locationId);
if (null == location)
throw new ArgumentNullException("Location-Id: " + locationId);
return location;
}
Diese Methode wiederum rufe ich in einer Methode > Schleife auf:
for (int i = 1; i <= values.GetLength(0); i++)
{
Employee employee = new Employee();
...
employee.Location = employeeRepository.GetLocation(locationId);
...
employees.Add(employee);
}
Innerhalb der For-Schleife werden Objekte erstellt, einer Liste hinzugefügt und am Ende wieder an das Repository gegeben:
employeeRepository.UpdateEmployees(employees);
Nun habe ich folgenden Effekt: jedes Objekt, für welches ich GetLocation aufgerufen habe, hat den EntityState "added", obwohl ich an keiner Stelle etwas schreibe, sondern nur auslese. Rufe ich also SaveChanges auf, verdoppeln sich die gesamten Einträge in der DB.
Ändere ich also den Aufruf innerhalb der Schleife folgendermaßen, habe ich den Verdopplungseffekt nicht, da ich den Repository-Aufruf nicht habe:
for (int i = 1; i <= values.GetLength(0); i++)
{
Employee employee = new Employee();
...
employee.Location = new Location() { Id = 1, Name = "Berlin" };
...
employees.Add(employee);
}
Hilfe! 😃
Vielen Dank im Voraus!
Hallo BillTuer,
throw new ArgumentNullException("Location-Id: " + locationId);
Ist ansich nicht korrekt da deine int locationId nicht null ist. ArgumentNullException sollte nur bei Parametern die null sind aber nicht dürfen geworfen werden.
Nun zu deinem Problem:
Am Anfang ist ein Objekt ja immer Detached, wie du sicherlich bemerkt hast. Dies bleib auch so lange so, solange du eines der folgenden Punkte nicht machst:*objectContext.Employee.AddObject(employee)
*employee.Location =meinAnderesObjekt
Wobei du sicherlich jetzt bemerkt hast das du mit employee.Location = employeeRepository.GetLocation(locationId) den 2.Punkt praktiziert. Also, ist dies kein Fehler, sondern Nomalzustand.
Gruß
Michael
Vielen Dank erstmal.
Aber wieso klappt es denn dann ohne den Repository-Aufruf? Dort weise ich doch dann quasi auch employee.Location =meinAnderesObjekt zu, oder nicht?
Aber wieso klappt es denn dann ohne den Repository-Aufruf?
Beziehst du dich auf das 3.Code Snippet?
Dort ist es anders.
Ich habe mich vorhin etwas unvollständig ausgedrückt. Ein Object bleibt so lange Detached bis es Punkt 1 erfährt, oder Punkt 2, mit der Beachtung dass das referenzierende Objekt sich schon im Objektcontext befindet.
Location loc = new Location();
emp.Location = loc; // loc nicht Added => emp auch nicht.
Location loc = context.Location.Singe(......);
emp.Location = loc // loc im ObjectContext => added => emp nach dieser Zeile auch.
Ich hoffe ich konnte es dir etwas verdeutlichen.
Ok, würde behaupten, dass ich das so weit verstanden habe 😉
Ich muss die Id also bis ins Repository reichen und mir dort das passende Objekt holen... Oder gibt es noch andere Lösungsansätze?
Ich muss die Id also bis ins Repository reichen und mir dort das passende Objekt holen
Ich verstehe nicht ganz was du darunter verstehts.
Aber normalerweise reicht es dass du bei jenen Employees welcher keiner Location vom Repository zugewiesen worden sind nicht das AddEmployee aufrufst. Am einfachsten geht diese Überprüfung über emp.EntityKey == EntityKey.Detached
Rufe ich also SaveChanges auf, verdoppeln sich die gesamten Einträge in der DB. Generell verhindert man doppelte Werte mit einem UNIQUE-Schlüssel, was sicherlich bei Employe etwas unnötig ist, denn 2 Employe können denselben Namen haben. Wobei in der anderen Hand sicherlich die Matrikelnummer eindeutig ist (wobei ich nicht weiß wie die Tabelle aussieht und dies auch nicht zur Diskussion steht). Na gut in diesem Fall bekommst du net UpdateException aber du hast eine Sicherheit dass doppelte Tuples vermieden werden.
Bei mir ging es um eine Excel-Datei, die komplette ausgelesen wird. Die ausgelesenen Daten sollten dann in ein entsprechendes Objekt überführt und in der DB gespeichert werden.
Ich reiche die Daten jetzt bis ins Repository durch und erstelle das Objekt erst dort und bei Bedarf, nicht mehr für alle Daten.
Klappt prima, vielen Dank für deine Hilfe.