Laden...

Update Child-Entity mit 1:n Beziehung

Erstellt von sittingduck vor 10 Jahren Letzter Beitrag vor 10 Jahren 1.271 Views
S
sittingduck Themenstarter:in
4 Beiträge seit 2013
vor 10 Jahren
Update Child-Entity mit 1:n Beziehung

verwendetes Datenbanksystem: sqlite

Hallo Zusammen,

Problem - Fehlermeldung:
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.

Augangslage:
FamilyEntity welche aus 1 ParentEntity und 0..n ChildEntity bestehen.

in Main lade ich zunächst die FamilyEntity aus der GUI und dann aktualisiere dies.
Beim Versuch ein neue ChildEntity hineinzufügen wurde o. g. Fehlermeldung ausgelöst.

Ich danke euch für eure Zeit meinen Beitrag zu lesen und freue mich auf jeder Hinweis.

Grussendem Gruss

sittingDuck

voin Main()
{
     var db = new FamilenEntities();
     FamilyEntity ff = GUI.GetFamily();
     ff.UpdateRelatedEntites(db);
     db.dispose();
}

in der GUI:


FamilyEntity GetFamily()
{
    FamilyEntity = famBindingSource.DataSource as FamilyEntity;
    
    BindingSource bs = bindingNavigator.DataSource;
    
    foreach(ChildEntity c in bs)
    {
        FamiliyEntity.childern.add(c);
    }
}

In der DataUpdateKlasse:


static void UpdateRelatedEntities(this FamilyEntity fam, FamilienEntities context)
{
     var rec = context.families.FirstOrDefault(f=> f.guid == fam.guid);
     context.families.Attach(rec)
     context.families.ApplyCurrentValues(fam)
    
    // Synchronisieren
    foreach(ChildEntity c in fam.children)
    {
         var crc = context.childern.Where(f=> f.guid == fam.guid);
         if(crc.count()<1)
         {
              // FEHLER - 
              context.children.AddObject(c);
         }    
     }
}
M
19 Beiträge seit 2012
vor 10 Jahren

Ich denke der Fehler liegt hier:

    foreach(ChildEntity c in fam.children)
    {
//Du prüfst hier ob eine Child.Guid der Family.Guid entspricht - was ja nie der Fall sein sollte.
         var crc = context.childern.Where(f=> f.guid == fam.guid);
         if(crc.count()<1)
         {
              // FEHLER -
              context.children.AddObject(c);
         }
     }

Es sollte wohl eher so aussehen:

    foreach(ChildEntity child in fam.children)
    {
         var crc = context.childern.Where(childInChildren => childInChildren.guid == child.guid);
         if(crc.count()<1)
         {
              context.children.AddObject(child);
         }
     }

S
sittingduck Themenstarter:in
4 Beiträge seit 2013
vor 10 Jahren

Hallo MATSE01,

Vielen Dank für deine Antwort,

Die Child.gui Prüfung dient dazu um zu unterscheiden wenn die ChildEntity bereits vorhanden ist, dann wird den attach und applycurrentvalues genutzt (welche nicht weiter ausgeführt wurde)

Struktur der Children-Tabelle:


id -> Automatisch aufsteigend
guid -> GUID
geschlecht -> 
etc

1 Familie hat dann N children.

Was mich wahnsinnig macht ist die tatsache wenn es adHoc neue objekt erstellt würde, wird die AddObject Vorgang einwandfrei laufen.

foreach(ChildEntity c in fam.children)
{
         var crc = context.childern.Where(f=> f.guid == fam.guid);
         if(crc.count()<1)
         {
              ChildEntity nchild = new ChildEntity
              {
                   guid = fam.guid,
                   geschlecht = fam.geschlecht
                  etc             = fam.etc
              }
              // ERZEUGT KEIN FEHLER -
              context.children.AddObject(nchild);
         }
}

Wenn meine Entity jetzt 50 Eigenschaften hätte, dann ist solche lösung nicht praktikabel.

Für weitere Kommentare/ Hinweis bin ich euch sehr dankbar

M
19 Beiträge seit 2012
vor 10 Jahren

Hallo sittingduck,

bei dem "adhoc" Beispiel - läßt du dein Problem ja auch weg: die ID.

Prüfe doch auch auf die ID in der foreach:

var crc = context.childern.Where(f=> f.guid == fam.guid || c.id == f.id);

Das sollte funktionieren - nur mußt du nun noch mehr Fälle betrachten (IDs gleich und GUIDs ungleich, etc.)

S
sittingduck Themenstarter:in
4 Beiträge seit 2013
vor 10 Jahren

Hallo MATSE01,

Vielen Dank für die rasche Antwort.

Dein Vorschlag habe ich hineingebaut (&& anstatt ||), es hat leider nicht geklappt. Ich bekomme immer noch die Fehlermeldung:
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.

Evtl. könnte folgende Erklärung dich dabei helfen mein Problem besser zu verstehen.
Start -> getFamilyEntity(string FamGuid) as FamilyEntity
Übergabe an Family GUI -> famBindingSource.DataSource = FamilyEntity
Übergabe an Child GUI -> childBindingSource.DataSource = FamilyEntity.children (anzahl=0)

Fazit = die GUI des Familiy objekt bleibt konstant (Update). deren unter objekt: children hat jetzt anstatt 0 anzahl, 5 neue datensatz mit id als Primary key.
Der Guid jedoch soll gleich bleiben (secondary)

Get Prozess in GUI

FamilyEntity uFam =  famBindingSource.DataSource;

BindingSource bs = bindingNavigator.DataSource; // (anzahl children = 5)

foreach(ChildEntity c in bs)
{
    uFam.childern.add(c);
}

Update

static void UpdateRelatedEntities(this FamilyEntity fam, FamilienEntities context)
{
     var rec = context.families.FirstOrDefault(f=> f.guid == fam.guid);
     context.families.Attach(rec)
     context.families.ApplyCurrentValues(fam)

    // Synchronisieren
    foreach(ChildEntity c in fam.children)
    {
         var crc = context.childern.Where(f=> f.guid == fam.guid && f.id == fam.id);
         if(crc.count()<1)
         {
              // FEHLER -
              context.children.AddObject(c);
         }
     }
}

ich habe rec.children.add(c) auch versucht, es hat auch nicht geklappt.

Danke vorab für die Hilfe

M
19 Beiträge seit 2012
vor 10 Jahren

Wie gesagt, muss ein "oder" sein, da ja sonst die ID schon vorkommt => Führt zu deiner Fehlermeldung.

Zum Verständnis noch mal der Aufbau deiner Tabellen:

T_Family (P_GUID, ...)
T_Children(P_ID, F_FamilyGUID, ...)

Wenn dem so ist, brauchst du die Abfrage nach den GUIDs gar nicht bzw. nicht in dieser Form, sondern nur um die Family zu bestimmen.

S
sittingduck Themenstarter:in
4 Beiträge seit 2013
vor 10 Jahren

Also die Tabellenaufbau ist nicht exact so, sondern

T_Family (F_FamilyGUID, ...)
T_Children(P_ID, F_FamilyGUID, ...)

Hätte dort ODER stehen dann kann man nicht mehr explicit die Children filtern, welche zu familie mit GUID gehören.

und wenn ich neue Child hineinfügen möchte habe ich deren GUID vorher mit dem aktiven Familie eingestellt.

Ich brauche die Anfrage um ein abgleich durchzufuhren neue gegen bestehende Children.