Linq - Group Join - Synatax Probleme

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 160 Antworten in diesem Thema. Der letzte Beitrag () ist von StGo.

    StGo schrieb:

    Wo mein Fehler liegt und was ihn auslöst habe ich in Post 104, 107, 110, 112 beschrieben.


    Nein, hast du nicht. Du hast nicht geschrieben, die Zeile löst die und die Fehlermeldung/Exception aus. Du hast ein Screenshot gepostet, der zeigt, dass du am Methodenkopf stehen bleibst (im Haltepunkt), mehr Infos habe ich nicht gefunden. Denn DANACH wurdest du gefragt, warum du nicht auf .Current Is Nothing prüfst und du sagtest nur, dass das nicht geht. Ohne den Code zu posten, mit dem du das ausprobiert hast (nur den falschen auskommentierten Code, der syntaktisch nicht geht).

    stürtzt bei mir nicht ab.


    VB.NET-Quellcode

    1. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    2. 'Zentriert starten
    3. Dim Bildschirm As Screen = Screen.PrimaryScreen
    4. Location = New Point(Bildschirm.Bounds.Left + (Bildschirm.Bounds.Width - Width) \ 2, Bildschirm.Bounds.Top)
    5. 'Reiter verstecken
    6. 'TabControl1.Alignment = TabAlignment.Bottom
    7. TabControl1.SizeMode = TabSizeMode.Fixed
    8. TabControl1.ItemSize = New Size(0, 1)
    9. TabControl1.Appearance = TabAppearance.Buttons
    10. TabControl1.ResumeLayout()
    11. 'TabControl2.Alignment = TabAlignment.Bottom
    12. TabControl2.SizeMode = TabSizeMode.Fixed
    13. TabControl2.ItemSize = New Size(0, 1)
    14. TabControl2.Appearance = TabAppearance.Buttons
    15. TabControl2.ResumeLayout()
    16. 'Daten generieren
    17. datenGenerieren()
    18. End Sub


    Kommentier mal bitte Zeile 20 aus. Jetzt werden jedes mal neue Datengeneriert. Wenn ich aber welche aus dem xml File laden will taucht das Problem auf. "Datei -> laden aus xml"
    Und ewig grüßt das Murmeltier... ;(
    Genau das behandeln wir seit Post#96, welches am Donnerstag um 16:06 gepostet wurde... DIe Rätsels Lösung wurde ziemlich sofort gepostet und vom TE abgelehnt, ohne seitdem ein einziges Mal erklärt haben, warum.
    Also beim mir erzeugt die Variante einen Fehler beim Start:

    VB.NET-Quellcode

    1. Option Strict On
    2. Imports System.IO
    3. Public Class frmMasterDetail
    4. Private _Datafile As New FileInfo("Dataset_Stammdaten.xml")
    5. Private Sub MenuStrip1_MenuClicked(ByVal Sender As Object, ByVal e As EventArgs) Handles DatenGenerierenToolStripMenuItem.Click, SaveToXMLToolStripMenuItem.Click, LadenAusXMLToolStripMenuItem.Click
    6. Select Case True
    7. Case Sender Is DatenGenerierenToolStripMenuItem
    8. datenGenerieren()
    9. Case Sender Is SaveToXMLToolStripMenuItem
    10. speicherToXml()
    11. Case Sender Is LadenAusXMLToolStripMenuItem
    12. ladenVonXml()
    13. End Select
    14. End Sub
    15. Private Sub datenGenerieren()
    16. 'Daten generieren
    17. Dim AnzahlZuGenerierendenDatensaetze As Integer = 19
    18. Dim tmp As Integer
    19. Dim tmpXls As Integer
    20. Dim tmpPdf As Integer
    21. Dim tmpDateityp As String
    22. Dim Cell As String
    23. Dim Bereich As String
    24. Dim rnd As New Random
    25. DsStammdaten.Clear()
    26. 'Tabelle Stammdaten generieren
    27. For i = 0 To AnzahlZuGenerierendenDatensaetze
    28. tmp = rnd.Next(1, 3)
    29. Select Case tmp
    30. Case 1
    31. tmpDateityp = "xls"
    32. Case 2
    33. tmpDateityp = "pdf"
    34. Case Else
    35. tmpDateityp = "error"
    36. End Select
    37. DsStammdaten.Stammdaten.AddStammdatenRow(i, "C:\Eingabepfad\hier liegt mein Dokument" & i, "C:\Ausgabepfad\hier wird es abgelegt" & i, tmpDateityp)
    38. Next
    39. 'Tabelle XLS generieren
    40. For j = 0 To AnzahlZuGenerierendenDatensaetze
    41. If DsStammdaten.Stammdaten.Rows(j).Item(4).ToString = "xls" Then
    42. tmpXls = rnd.Next(1, 5)
    43. Select Case tmpXls
    44. Case 1
    45. Cell = "A"
    46. Case 2
    47. Cell = "B"
    48. Case 3
    49. Cell = "C"
    50. Case 4
    51. Cell = "D"
    52. Case Else
    53. Cell = "error"
    54. End Select
    55. Dim tmpIdStammdaten = DsStammdaten.Stammdaten(j)
    56. DsStammdaten.XLS.AddXLSRow(tmpIdStammdaten, CStr(j), Cell & j)
    57. End If
    58. Next
    59. 'Tabelle PDF generieren
    60. For k = 0 To AnzahlZuGenerierendenDatensaetze
    61. If DsStammdaten.Stammdaten.Rows(k).Item(4).ToString = "pdf" Then
    62. tmpPdf = rnd.Next(1, 4)
    63. Select Case tmpPdf
    64. Case 1
    65. Bereich = "X"
    66. Case 2
    67. Bereich = "Y"
    68. Case 3
    69. Bereich = "Z"
    70. Case Else
    71. Bereich = "error"
    72. End Select
    73. Dim tmpIdStammdaten = DsStammdaten.Stammdaten(k)
    74. DsStammdaten.PDF.AddPDFRow(tmpIdStammdaten, "Der Text wird im Bereich: " & Bereich & k & " gesucht.")
    75. End If
    76. Next
    77. End Sub
    78. Private Sub speicherToXml()
    79. Me.Validate()
    80. DsStammdaten.WriteXml(_Datafile.FullName)
    81. MessageBox.Show("Daten erfolgreich gespeichert (siehe Projektverzeichnis\bin\Debug)")
    82. End Sub
    83. Private Sub ladenVonXml()
    84. DsStammdaten.Clear()
    85. If _Datafile.Exists Then
    86. DsStammdaten.ReadXml(_Datafile.FullName)
    87. MessageBox.Show("Daten erfolgreich geladen")
    88. Else
    89. MessageBox.Show("Keine Daten vorhanden")
    90. End If
    91. End Sub
    92. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    93. 'Zentriert starten
    94. Dim Bildschirm As Screen = Screen.PrimaryScreen
    95. Location = New Point(Bildschirm.Bounds.Left + (Bildschirm.Bounds.Width - Width) \ 2, Bildschirm.Bounds.Top)
    96. 'Reiter verstecken
    97. 'TabControl1.Alignment = TabAlignment.Bottom
    98. TabControl1.SizeMode = TabSizeMode.Fixed
    99. TabControl1.ItemSize = New Size(0, 1)
    100. TabControl1.Appearance = TabAppearance.Buttons
    101. TabControl1.ResumeLayout()
    102. 'TabControl2.Alignment = TabAlignment.Bottom
    103. TabControl2.SizeMode = TabSizeMode.Fixed
    104. TabControl2.ItemSize = New Size(0, 1)
    105. TabControl2.Appearance = TabAppearance.Buttons
    106. TabControl2.ResumeLayout()
    107. 'Daten generieren
    108. 'datenGenerieren()
    109. End Sub
    110. Private Sub StammdatenBindingSource_CurrentChanged(sender As Object, e As EventArgs) Handles StammdatenBindingSource.CurrentChanged
    111. If StammdatenBindingSource.Current Is Nothing Then
    112. Return
    113. Else
    114. 'If StammdatenBindingSource.Current <> 0 Then
    115. Dim rwStamm = DirectCast(DirectCast(StammdatenBindingSource.Current, DataRowView).Row, dsStammdaten.StammdatenRow)
    116. 'If rwStamm.RowState <> DataRowState.Detached Then
    117. Select Case rwStamm.Dateityp
    118. Case "xls"
    119. TabControl1.SelectedIndex = 1
    120. TabControl2.SelectedIndex = 1
    121. Case "pdf"
    122. TabControl1.SelectedIndex = 2
    123. TabControl2.SelectedIndex = 2
    124. Case Else
    125. TabControl1.SelectedIndex = 0
    126. TabControl2.SelectedIndex = 0
    127. End Select
    128. End If
    129. End Sub
    130. Private Sub StammdatenDataGridView_EditingControlShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) Handles StammdatenDataGridView.EditingControlShowing
    131. Dim myButton As New Button
    132. With myButton
    133. .Dock = DockStyle.Right
    134. .Name = "btnOpen"
    135. .Text = "..."
    136. .Width = 25
    137. End With
    138. If Not StammdatenDataGridView.Controls.ContainsKey(myButton.Name) Then
    139. StammdatenDataGridView.EditingPanel.Controls.Add(myButton)
    140. End If
    141. myButton.BringToFront()
    142. End Sub
    143. Private Sub cmdXlsLoeschen_Click(sender As Object, e As EventArgs) Handles cmdXlsLoeschen.Click
    144. End Sub
    145. Private Sub cmdPdfLoeschen_Click(sender As Object, e As EventArgs) Handles cmdPdfLoeschen.Click
    146. End Sub
    147. Private Sub cmdXlsSpeichern_Click(sender As Object, e As EventArgs) Handles cmdXlsSpeichern.Click
    148. End Sub
    149. Private Sub cmdPdfSpeichern_Click(sender As Object, e As EventArgs) Handles cmdPdfSpeichern.Click
    150. End Sub
    151. End Class


    und zwar an dieser Stelle (Zeile 10) im dsStammdaten.Designer

    VB.NET-Quellcode

    1. <Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
    2. Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")> _
    3. Public Property Dateityp() As String
    4. Get
    5. Try
    6. Return CType(Me(Me.tableStammdaten.DateitypColumn), String)
    7. Catch e As Global.System.InvalidCastException
    8. Throw New Global.System.Data.StrongTypingException("Der Wert für Spalte Dateityp in Tabelle Stammdaten ist DBNull.", e)
    9. End Try
    10. End Get
    11. Set(value As String)
    12. Me(Me.tableStammdaten.DateitypColumn) = value
    13. End Set
    14. End Property

    Du hast das DataSet zu dem Zeitpunkt noch gar nicht geladen und willst rwStamm.DateiTyp abfragen. Normalerweise lädt man am Anfang des Programms gleich das Dataset...

    Du kannst einen Flag (eine boolsche Variable) "IsLoad" einfügen, welchen du nach dem DataSet befüllen (entweder per XML oder per Datengenerieren) auf True setzt. Diesen Flag fragst du am Anfang von .CurrentChanged ab und gehst raus, wenn er auf False steht.
    Ja ich denke das könnte der Lösung beiträglich sein. Wie gesagt. Vermutet hatte ich die Richting ja schon:


    Der Fehler tritt auf, wenn auf die Bindingsource zugegriffen wird. Zu dem Zugriff steht dort aber nichts drin.


    Dann schaue ich mal wie ich das umsetze.

    Danke
    Guten Morgen,

    @EDR
    Das habe ich überlesen. Es funktioniert wie du es sagst. Entschuldige bitte. Habe ich wirklich nicht gesehen.

    Für alle die mitlesen und den richtigen Code jetzt sehen wollen:

    VB.NET-Quellcode

    1. Private Sub StammdatenBindingSource_CurrentChanged(sender As Object, e As EventArgs) Handles StammdatenBindingSource.CurrentChanged
    2. If StammdatenBindingSource.Current Is Nothing Then
    3. Return
    4. Else
    5. Dim rwStamm = DirectCast(DirectCast(StammdatenBindingSource.Current, DataRowView).Row, dsStammdaten.StammdatenRow)
    6. If rwStamm.RowState <> DataRowState.Detached Then
    7. Select Case rwStamm.Dateityp
    8. Case "xls"
    9. TabControl1.SelectedIndex = 1
    10. TabControl2.SelectedIndex = 1
    11. Case "pdf"
    12. TabControl1.SelectedIndex = 2
    13. TabControl2.SelectedIndex = 2
    14. Case Else
    15. TabControl1.SelectedIndex = 0
    16. TabControl2.SelectedIndex = 0
    17. End Select
    18. End If
    19. End If
    20. End Sub
    Das bedeutet nicht unbedingt "leer", sondern es bedeutet: "in keiner DataTable" - mit der Auswirkung, das verknüpfte Datensätze nicht abrufbar sind, denn der Datensatz ist noch nicht verknüpft.
    Daher der Fehler bei StGo, wenn er versucht, auf die ChildRows der Detachten Zeile zuzugreifen.

    (Und solch Datensatz wird natürlich nicht mit abgespeichert.)

    ja, irgendwann kann man sich mal mit den Rowstates befassen: ObjectBrowser gucken, welche es gibt, Testprojekt machen, und rumspielen mit
    • rw=MyDataTable.NewMyRow
    • MyDataTable.Add(rw)
    • rw.Delete
    • rw.MyProperty=aValue
    • MyDataTable.AcceptChanges
    • MyDataTable.RejectChanges
    • MyDataset.HasChanges / .GetChanges
    und jeweils gucken, welche Auswirkungen das auf rw.Rowstate hat.
    Der Rowstate ist hauptsächlich das Kernstück der Änderungsverfolgung, und bleibt damit üblicherweise im Hintergrund, aber zB. die HinzufügeZeile einer BindingSource hat RowState.Detached.

    Ja, und bei Rowstate.Detached existieren die DataRelations noch nicht, und bei Rowstate.Deleted sind gar keine Werte abrufbar.

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

    Ich muss euch nochmal etwas fragen. Wenn ich das Dataset typisiert erstellt habe und meine enthaltenen Tables in einem DGV anzeige und die Daten durch das DGV „verschmelze“ etspricht dies einem Join – oder?Konkret hier aus dem Beispiel Programm:Stammdaten sind über die Relation Id – IdStammdaten mit den Daten XLS verbunden. Im DGV Master/Detail View werden die Daten aus den einzelnen Tabellen entsprechend angezeigt. (Das DGV weiss auch, dass die Spalte Id aus den Stammdaten mit der Spalte IdStammdaten aus dem XLS Table zusammengehört.)

    1. Wenn ich eine Zeile in den Stammdaten hinzufüge muss mir das DGV doch irgendwie eine passende Zeile im DetailView anbieten. Wie realisiere ich das?

    2. Wenn ich kein DGV habe und Daten aus einem 2d Array in mein typisiertes Dataset laden möchte stehe ich vor dem Problem, dass ich die Parent/Child Beziehung berücksichtigen muss. Wie gehe ich das Problem an? (Mir ist klar das dieser Falle eher ein theoretischer ist da man das DGV normalerweise für dieses Problem einsetzt – sieh Frage 1)


    Zu 2.
    Stammdaten:
    Id | Nr | Eingabepfad | Ausgabepfad | Dateityp
    Autoincrement | Autoincrement | String | String | String

    XLS:
    Id | IdStammdaten | Blatt | Zeile
    Autoincrement | Fremdschlüssel von Stammdaten | String | String

    Im Falle einer unverkrüpften Tabelle würde ich beide Tabellen auf diese Weise füllen:

    VB.NET-Quellcode

    1. DataSetNeu.DtStammdaten.AddDtStammdatenRow(arrayResult(i, 0), arrayResult(i, 1), "xls")
    2. DataSetNeu.DtXls.AddDtXlsRow(arrayResult(i, 2), arrayResult(i, 3))


    Das Problem was ich jetzt habe ist das ich keine Idee haben wie ich den zusammenhang der Tabellen gegenüber dem Compiler klar mache.

    Danke

    Da habe ich dir EXAKT das geschrieben, was du jetzt schon wieder fragst.


    Ach ja? Ich würde sagen du hast auf dem Autoinkrement rumgehackt. Was im endefekt etwas undeutlich beschrieben war aber in der Syntax richtig.

    Wie man hier sieht:

    VB.NET-Quellcode

    1. DataSetNeu.DtStammdaten.AddDtStammdatenRow(arrayResult(i, 0), arrayResult(i, 1), "xls")

    übergeb ich drei Strings wie es das Dataset verlangt. Aber dsa ist auch gar nicht die Frage!

    Ein Datensatz ist auf zwei Tabellen "aufgeteilt". Also muss ich im Prinzip Eingabepfad | Ausgabepfad | Dateityp | Blatt | Zeile übergeben da die Id in den Stammdaten generiert wird und gleichzeitig Fremdschlüssel in der XLS Tabelle ist kann ich hier nichts übergeben. Genau da liegt dsa Problem! (Die Spalte Nr in den Stammdaten wird auch automatisch generiert.)

    Die Frage ist also: Muss die Daten so (in einem Rutsch) Eingabepfad | Ausgabepfad | Dateityp | Blatt | Zeile übergeben oder

    VB.NET-Quellcode

    1. DataSetNeu.DtStammdaten.AddDtStammdatenRow(arrayResult(i, 0), arrayResult(i, 1), "xls")
    2. DataSetNeu.DtXls.AddDtXlsRow(arrayResult(i, 2), arrayResult(i, 3))

    in zwei Schritten? Wenn in zwei Schritten müsste ich einen "Platzhalter" hier

    VB.NET-Quellcode

    1. DataSetNeu.DtXls.AddDtXlsRow(PLATZHALTER, arrayResult(i, 2), arrayResult(i, 3))


    einfügen.

    @sonne75
    Wo hast du das beschrieben/erklärt?

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „StGo“ ()

    sonne75 schrieb:

    Post #69, vor einer Woche:


    sonne75 schrieb:

    Zu dem Rest sagte ich schon, du machst es komplett falsch - es wird ROW erwartet, die Row bekommst du als Rückgabeparameter von AddXXRow(), .Stammdaten(i) ist der falsche Ansatz.

    VB.NET-Quellcode

    1. Dim rwStammdaten=DsStammdaten.Stammdaten.AddStammdatenRow("C:\Eingabepfad\hier liegt mein Dokument" & i, "C:\Ausgabepfad\hier wird es abgelegt" & i, tmpDateityp)
    2. DsStammdaten.PDF.AddPDFRow(rwStammdaten, "Der Text wird im Bereich: " & Bereich & k & " gesucht.")


    So geht das.


    StGo schrieb:

    Wo hast du das beschrieben/erklärt?


    Ich verstehe nicht, ob du mich einfach verarschst oder wirklich so ...."Platzhalter".... bist.