LINQ2SQL Update klappt nicht Fehler: "Eine Entität, deren Schlüssel bereits verwendet wird, kann nicht hinzugefügt werden"

  • VB.NET

Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    LINQ2SQL Update klappt nicht Fehler: "Eine Entität, deren Schlüssel bereits verwendet wird, kann nicht hinzugefügt werden"

    Hallo liebe VB-Fans,

    ich brauche mal wieder Eure Hilfe. :S
    Ich glaube, dass das wohl nie aufhört.

    Erst einmal der Quelltext:

    VB.NET-Quellcode

    1. Private Sub btnApply_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnApply.Click
    2. Dim dtKontoAnlegen = (From k2 In DsCC11.KONTO_ANLEGEN _
    3. Select k2)
    4. Dim dataContext As New CC1DataContext()
    5. Dim kAuszug = (From k In dataContext.KONTOAUSZUG _
    6. Select k)
    7. For Each row In dtKontoAnlegen
    8. If Not row.IsAnlegenNull AndAlso row.Anlegen = True Then
    9. Dim koAusz As New KONTOAUSZUG
    10. With koAusz
    11. ' Prüfen ob in Kontoauszug schon ein Datensatz vorhanden ist
    12. If kAuszug.Count = 0 Then
    13. ' Hier wird ein neuer Datensatz angelegt
    14. Dim g As Guid = Guid.NewGuid
    15. .idKontoauszug = g
    16. .BankNameKontrahent = row.Bank
    17. .KtoKontrahent = row.Kontonummer
    18. .BLZKontrahent = row.BLZ
    19. Else
    20. Dim str5 As String = row.idBankKonto.ToString
    21. Dim str6 As String = koAusz.idKontoauszug.ToString
    22. For Each row2 In kAuszug
    23. 'Wenn es schon exisitiert, erfolgt nur ein Update
    24. If row2.BankNameKontrahent = row.Bank AndAlso row2.KtoKontrahent = row.Kontonummer _
    25. AndAlso row2.BLZKontrahent = row.BLZ Then
    26. .BankNameKontrahent = row.Bank
    27. .KtoKontrahent = row.Kontonummer
    28. .BLZKontrahent = row.BLZ
    29. End If
    30. Next
    31. End If
    32. End With
    33. dataContext.SubmitChanges()
    34. MessageBox.Show("Änderungen wurden erfolgreich in die Datenbank übernommen")
    35. End If
    36. Next
    37. End Sub


    Kleine Erläuterung hierzu:
    ktoAnlegen ist aus dem Grid Anlegen und eine tempörare Table.
    kAuszug ist eine Table aus der DB.

    Die Daten sollen, wenn sie nicht in der DB vorhanden sind hineingeschrieben werden. Das klappt soweit. Ich hänge derzeit nur leider im Else-Block.

    Bei dataContext.SubmitChanges() bleibt der Debugger stehen und es kommt folgende Fehlermeldung:
    "Eine Entität, deren Schlüssel bereits verwendet wird, kann nicht hinzugefügt werden"

    Das verstehe ich nicht so ganz. Ich will ja keinen neuen Datensatz hinzufügen oder so etwas. Und was bedeutet hier in dem Kontext verwendet? Wie und wo verwende ich denn da etwas?

    Habe Ihr vielleicht einen Ratschlag oder einen Lösungsansatz für mich?
    Auch wenn Ihr Euch nicht sicher seid, ob es klappen könnte, postet ruhig etwas. Ich werde es schon ausprobieren. ;)

    Danke!!!


    Viele Grüße
    Trigoor

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Trigoor“ () aus folgendem Grund: EDIT: Ich hoffe doch, dass der Quelltext bei Euch richtig angezeigt wird. EDIT 2: Seltsamweise war der SC wieder linksbündig. Habe ihn jetzt wieder richtig ausgerichtet.

    Hi..,

    lesbare Form. Habe mal Deine Hinweis-Link angeschaut, und nun ja, bei mir sieht es okay aus. Ist ganz normal eingerückt. Hmm, sowas kann ja auch nicht am Browser liegen. Sowas ist ja Unfug. Werde es halt noch einmal editieren.

    Ach zum Problem:
    Hatte ein kleines Problem mit dem Insert (also neuen Datensatz anlegen). Hatte zuerst die Checkbox und dann auf DBNULL geprüft, und es kam zu einer Exception. Dann habe es ausgetauscht und dann klappte es wieder. Aber das ist doch eigentlich egal. Vielleicht klappt es später auch wieder nicht mehr. Vorher hatte es auch schon mal geklappt und mal auch wieder nicht..nun ja, mal testen. Hoffe doch, dass der Zustand so bleibt.

    Nur die Sache mit dem Update kapiere ich echt nicht. Jetzt kommt zwar keine Exception, aber es wird trotzdem ein neuer Datensatz angelegt. Hmm... ?(

    Nun ja, vielleicht komme ich ja noch alleine darauf.
    Ansonsten ist Hilfe Willkommen!! ;)

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „Trigoor“ ()

    Trigoor schrieb:

    Habe mal Deine Hinweis-Link angeschaut, und nun ja, bei mir sieht es okay aus.

    mach dochmal ein screenshot, wie bei dir die Vorschau aussieht, inklusive Eingabefeld. Lohnt sich glaub schon die Mühe, das mal i.O. zu bringen - du wirst ja öfter nochmal was posten wollen. ;)


    Trigoor schrieb:

    Nur die Sache mit dem Update kapiere ich echt nicht. Jetzt kommt zwar keine Exception, aber es wird trotzdem ein neuer Datensatz angelegt. Hmm...

    Sollte ich jetzt wissen, wovon du redest?

    Das einzige, wassichweiß, ist, dass du deinen Code inzwischen weiterentwickelt hast - von der "Sache mit dem Update" höre ich hier erstmalig.
    Hallo ErfinderDesRades,

    habe den Eintrag mit dem Quellcode schon editiert gehabt. Sagt bloss, das bei Euch(oder Dir), der Quellcode immer noch unleserlich ist.
    Das mit dem Screenshot kann man doch nicht immer machen, und zudem kann man dann den Code per Copy&Paste auch nicht übernehmen. ?(

    Okay, aber hier kommt trotzdem ein Screenshot:



    Uploaded with ImageShack.us

    Und hier ein Screenshot vom Eingabefeld:



    Uploaded with ImageShack.us


    Was mir auffällt. Bem Erstellen eines Posts setze ich den Quelltext richtig eingerückt ein. Er wird dann auch in der Vorschau (bei mir) richtig angezeigt. Beim erneuten editieren (siehe Screenshot) ist der Text auf einmal linksbündig. Aber auch die Vorschau funktioniert bei mir und der Quelltext sieht ordentlich formatiert aus. Bis jetzt hatte ich doch bei den anderen Threads keine Probleme damit..hmmmm... ?(

    Liegt vielleicht auch an der Board-Software?? Kann das sein??

    Soviel habe ich am Quellcode auch nicht geändert.

    Siehe hier:

    VB.NET-Quellcode

    1. Private Sub btnApply_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnApply.Click
    2. Dim dtKontoAnlegen = (From k2 In DsCC1.KONTO_ANLEGEN _
    3. Select k2)
    4. Dim dataContext As New CC1DataContext()
    5. Dim kAuszug = (From k In dataContext.KONTOAUSZUG _
    6. Select k)
    7. For Each row In dtKontoAnlegen
    8. If Not row.IsAnlegenNull AndAlso row.Anlegen = True Then
    9. Dim koAusz As New KONTOAUSZUG
    10. Dim gs As New GESELLSCHAFT
    11. With koAusz
    12. ' Prüfen ob in Kontoauszug schon ein Datensatz vorhanden ist
    13. If kAuszug.Count = 0 Then
    14. ' Hier wird ein neuer Datensatz angelegt
    15. Dim g As Guid = Guid.NewGuid
    16. .idKontoauszug = g
    17. .BankNameKontrahent = row.Bank
    18. .KtoKontrahent = row.Kontonummer
    19. .BLZKontrahent = row.BLZ
    20. Else
    21. Dim str5 As String = row.idBankKonto.ToString
    22. Dim str6 As String = koAusz.idKontoauszug.ToString
    23. For Each row2 In kAuszug
    24. 'Wenn es schon exisitiert, erfolgt nur ein Update
    25. If row2.BankNameKontrahent = row.Bank AndAlso row2.KtoKontrahent = row.Kontonummer _
    26. AndAlso row2.BLZKontrahent = row.BLZ Then
    27. .BankNameKontrahent = row.Bank
    28. .KtoKontrahent = row.Kontonummer
    29. .BLZKontrahent = row.BLZ
    30. End If
    31. Next
    32. End If
    33. dataContext.KONTOAUSZUG.InsertOnSubmit(koAusz)
    34. End With
    35. End If
    36. Next
    37. dataContext.SubmitChanges()
    38. MessageBox.Show("Änderungen wurden erfolgreich in die Datenbank übertragen")
    39. End Sub


    Wird er dieses Mal richtig angezeigt? Oder soll ich nen Screenshot machen? :D
    dein letzter Code ist richtig.
    Und an deim Screenshot sehe ich, dass dus genau anders (also falsch) machst, wie ich in VB-Tag richtig benutzen beschreibe.

    Nicht den Editor-Editor der Forums benutzen, sondern den Quellcode-Editor!

    Trigoor schrieb:

    Liegt vielleicht auch an der Board-Software?? Kann das sein??

    Was meinst du, wozu ich VB-Tag richtig benutzen entworfen habe, und bei Bedarf (und das ist häufig) darauf verlinke?

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Ja, klar. Ich benutze den Quellcode-Editor. Immer. Wäre ja ein Akt jede Zeile per Hand einzurücken. Wird halt per Copy&Paste gemacht. Wie soll man denn das anders auch machen. Also, ich weiss auch nicht so recht woran es lag...nun ja solange es klappt.

    @all:
    Bitte bei so etwas mich IMMER darauf hinweisen. Wie schon gesagt, bei mir sieht es richtig angezeigt aus.
    Nein, habe ich nicht. Wie schon gesagt. Der Quelltext war beim erneuten editieren linksbündig. Beim ersten Erstellen des Posts war er richtig eingerückt.

    EDIT: Da bin ich mir ziemlich sicher. Aber egal, da werde ich in Zukunft GENAU darauf achten.

    Ach, zum Thema. Hast Du eine Ahnung wo der Haken liegt?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Trigoor“ ()

    du meinst "die Sache mit dem Update"?

    Wie (in post#4) gesagt - die Frage müssteste nochmal vernünftig stellen, und wohl auch die neueste Code-Version zeigen.

    naja - auf die schnelle:
    ...aber es wird trotzdem ein neuer Datensatz angelegt. Hmm...

    Was erwartest du von einer Methode "InsertOnSubmit()" anderes, als dassn neuer Datensatz angelegt wird?
    Nun ja, vermutlich lag es daran.

    Habe...Dim koAusz As New KONTOAUSZUG....über die for-each-Schleife gesetzt. Ist ja klar, sonst erzeugt er ja immer ein neues Objekt und daran wird es wohl gelegen haben.

    Aber jetzt kommt wieder diese Exception wie in meinem Titel beschrieben.

    ErfinderDesRades schrieb:

    Wie (in post#4) gesagt - die Frage müssteste nochmal vernünftig stellen, und wohl auch die neueste Code-Version zeigen.

    Habe ich sie denn nicht vernünftig gestellt? Ich denke doch, dass ich mir Mühe gebe. Woran liegt es?
    Und die neuste Code-Version(Du meinst den Quelltext von mir?) ist es ja auch. Du hattest ja danach gefragt, und hatte es gepostet.

    ErfinderDesRades schrieb:

    Was erwartest du von einer Methode "InsertOnSubmit()" anderes, als dassn neuer Datensatz angelegt wird?

    Stimmt, Du hast ja Recht. Heisst ja auch "INSERTOnSubmit" und leider nicht "UpdateOnSubmit".
    Aber mit "InsertOnSubmit" geht es wohl auch. Siehe hier:
    msdn.microsoft.com/de-de/library/bb386931.aspx

    VB.NET-Quellcode

    1. ' Change the name of the contact.
    2. cust.ContactName = "New Contact"


    Okay, da fragt er gezielt nach der ID, aber es müsste ja auch so klappen, oder?

    VB.NET-Quellcode

    1. Dim cust As Customer = (From c In db.Customers _
    2. Where c.CustomerID = "ALFKI" Select c) .First()


    Wäre trotzdem sehr nett von Dir, wenn Du mir helfen könntest! Auch wenn Du nicht ganz zufrieden mit meinen Fragen und meinen Quellcodeveröffentlichungen bist. Will mich bei Dir nicht verbocken... ^^

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Trigoor“ ()

    was du mal probieren kannst, ist, diese nutzlosen Linq-Queries rauszuwerfen. Also die Anfangszeilen ändern zu

    VB.NET-Quellcode

    1. Private Sub btnApply_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnApply.Click
    2. Dim dtKontoAnlegen = DsCC1.KONTO_ANLEGEN
    3. Dim dataContext As New CC1DataContext()
    4. Dim kAuszug = dataContext.KONTOAUSZUG

    Jo, und dann findich die Schleife konfus.

    VB.NET-Quellcode

    1. For Each row In dtKontoAnlegen
    2. If Not row.IsAnlegenNull AndAlso row.Anlegen = True Then
    3. Dim koAusz As New KONTOAUSZUG
    4. Dim gs As New GESELLSCHAFT
    5. With koAusz
    6. '...
    Dieses If hat ühaupt keinen Else-Zweig, also wenn was passiert, dann, dass ein neuer KONTOAUSZUG geschaffen wird - ein Zweig fürs Updaten bereits vorhandener ist nicht gegeben.
    Hallo ErfinderDesRades,

    hey, das ist ja cool. Man brach ja diese Linq-Queries gar nicht. Was Du nicht alles weisst.. :D Von Dir kann mal viel lernen. :thumbsup:
    Dafür gibt es schon einmal ein "hilfreich"!!! :D

    Nun ja, dies Schleife hat keinen Else-Zweig, weil ich ja den nicht brauche.

    Ich prüfe ja schon bereits vorher, (im ersten IF-Zweig) ob der Tabelle KONTOAUSZUG was drin ist. Und das macht er ja auch. Nur er soll halt statt ein Insert ein Update dort (im ersten Else-Zweig) ausführen. Deswegen gibt es auch keinen zweiten Else-Zweig. Habe ich mich verständlich ausgedrückt? Oder habe ich Dich falsch verstanden? ?(

    Also einen Datensatz in die leere Tabelle KONTOAUSZUG hineinzuschreiben klappt, aber sobald ich 2 auswähle kommt auch diese Exception (siehe Titel).

    EDIT: Falsche Aussage (letzter Absatz). Jetzt führt er tatsächlich ein Update aus. Im Moment führt er nur Updates aus. Also wenn ich alle auswähle und dann auf den Button drücke updatet er natürlich nur den ersten Datensatz. Und so ist natürlich nur 1 Eintrag in der DB vorhanden.

    Aber das Ganze ist komplizierter. Habe nämlich zwei Methoden. Eine zum Füllen des Grids aus der MT940-Datei und dann eine Andere wiederum die zum Einlesen des Grids in die DB zuständig ist. Und paralell bin ich auch noch an nem anderem Grid(Auszüge) dran. Also, so ganz trivial ist das Ganze nicht. Gerade für einen der sich erst seit 3 Wochen so richtig mit VB und den DB auseinersetzt.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Trigoor“ ()

    Also solange du so machst:

    VB.NET-Quellcode

    1. Dim koAusz As New KONTOAUSZUG
    und dann so:

    VB.NET-Quellcode

    1. dataContext.KONTOAUSZUG.InsertOnSubmit(koAusz)
    und schließlich so:

    VB.NET-Quellcode

    1. dataContext.SubmitChanges()

    Solange kann man eiglich nix anneres erwarten, als dasser, wennüberhaupt, nur neue koAusz inserted.

    Wenn du iwas bestehendes ändern willst, musst du es halt aufsuchen - keinesfalls darfst du dann iwas mit New() machen.

    Also müste es iwie einen else-zweig geben, wo auf ein koAusz - Dings zugegriffen wird, welches bereits vorher existiert hat.

    Es geht doch ums Update einer KONTOAUSZUG - Entity, nicht um iwelche Updates der Datatable?
    Hallo ErfinderDesRades,

    Werde Deine 3 Codeschnipsel beherzigen wenn ich was updaten will.

    Aber es wollte und wollte nicht klappen. Dann hatte ich die Faxen satt und habe die Methode komplett neu geschrieben.
    Mir geht es erst einmal um das Update. Wenn das klappt, kann man sich um das Insert kümmern.

    Schau mal hier:

    VB.NET-Quellcode

    1. Private Sub btnApply_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnApply.Click
    2. Dim dtKontoAnlegen = DsCC1.KONTO_ANLEGEN
    3. Dim dataContext As New CCDataContext()
    4. Dim dcKONTOAUSZUG = dataContext.KONTOAUSZUG
    5. Dim koAusz As New KONTOAUSZUG
    6. For Each row In dtKontoAnlegen
    7. If Not row.IsAnlegenNull AndAlso row.Anlegen = True Then
    8. With koAusz
    9. .Währung = row.Währung
    10. ' Fall 1:
    11. 'dataContext.KONTOAUSZUG.InsertOnSubmit(koAusz)
    12. 'Fall 2:
    13. 'dcKONTOAUSZUG.InsertOnSubmit(koAusz)
    14. End With
    15. End If
    16. Next
    17. dataContext.SubmitChanges()
    18. MessageBox.Show("Änderungen wurden erfolgreich in die Datenbank übertragen")
    19. End Sub


    Ich habe beides ausprobiert. Vielleicht hätte es ja klappen können. Aber bei Fall 1 und Fall 2 kommt folgende Fehlermeldung:

    "Verletzung der PRIMARY KEY-Einschränkung "PK_KONTOAUSZUG". Ein doppelter Schlüssel kann in das Objekt "dbo.KONTOAUSZUG" nicht eingefügt werden. Der doppelte Schlüsselwert ist (00000000-0000-0000-0000-000000000000). Die Anweisung wurde beendet."

    Was soll denn das wieder bedeuten? Warum doppelter Schlüssel? Vergebe keine neue ID oder so etwas(habe es probiert(dann führt er einen insert aus)). Ich möchte lediglich den Eintrag Währung in der ersten Zeile ändern. Bin ich echt zu blöd für sowas 8| , oder wo liegt da der Haken? ?(


    Habe aus reiner Verzeiflung auch folgendes probiert.

    VB.NET-Quellcode

    1. .idKontoauszug = "00000000-0000-0000-0000-000000000000"
    2. .Währung = row.Währung


    Aber das klappt ja natürlich auch nicht. Das eine ist ne GUID und das andere ein String. Und mit CType geht es auch nicht, da es sich bei Guid um eine Structure und nicht um eine Klasse handelt. Und wenn bei der Aktion die Fehlermeldung kommen würde, wäre es ja klar, aber ansonsten.

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „Trigoor“ ()

    Hallo ErfinderDesRades,

    Du hast ja Recht. Ich brauche gar keine Instanz vom Datentyp KONTOAUSZUG anlegen.
    Und ich brauche auch kein InsertOnSubmit().
    Nur wusste ich nicht so recht was damit anzufangen, aber der Ansatz der von Dir kam half mir schon mal weiter.
    Habe es jetzt endlich hingekriegt. Und es ist echt einfach wenn man es weiss.

    Habe hier dazu einen Hinweis gefunden:
    weblogs.asp.net/scottgu/archiv…g-linq-to-sql-part-1.aspx

    Das hatte wenigstens geklappt.

    Bei mir sieht es "im Moment" so aus:

    VB.NET-Quellcode

    1. Dim koAus = (From k In dataContext.KONTOAUSZUG Where _
    2. k.BankNameKontrahent = row.Bank AndAlso _
    3. k.BLZKontrahent = row.BLZ AndAlso k.KtoKontrahent = _
    4. row.Kontonummer Select k).Single
    5. koAus.Währung = row.Währung
    6. dataContext.SubmitChanges()


    So langsam gefällt mir Linq to SQL immer besser. :)

    Greetz
    Trigoor

    Trigoor schrieb:

    So langsam gefällt mir Linq to SQL immer besser. :)

    kannst du schon einen Datensatz löschen? :evil:


    Edit: und dann hat Dataset immer noch den Vorzug, dasses so einen koAuszug quasi aus der Tasche zieht.

    Dein L2S-Verfahren hingegen setzt im Hintergrund eine Abfrage an die DB ab - es holt quasi den zu ändernden Datensatz erstmal neu aus der DB.
    Dabei halte ich es für höchstwahrscheinlich, dass dieser Datensatz in ieiner Weise bereits im Arbeitsspeicher ist - nur isses sehr umständlich, den aufzufinden.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()