Fehlerbehebung durch Option Strict so gut wie fertig

  • VB.NET
  • .NET 5–6

Es gibt 32 Antworten in diesem Thema. Der letzte Beitrag () ist von Achilleus.

    Fehlerbehebung durch Option Strict so gut wie fertig

    Hallo liebes Forum,

    ich habe mein Projekt nun mehr durch mit Option Strict ON.
    Ich konnte einiges lernen auch dank diesem Forum.

    Ein Fehler steht noch an bei den ich nicht weiter komme.

    Ich möchte aus einer DGV eine Zeile löschen mit dem Button Löschen (nur die Zeile die folgende ID enthält)

    Hier der CODE:

    VB.NET-Quellcode

    1. Private Sub ButtonDelete_Click(sender As Object, e As EventArgs) Handles ButtonDelete.Click
    2. If DataGridView1.RowCount = 0 Then
    3. MsgBox("Löschen nicht möglich, Tabellendaten sind leer", MsgBoxStyle.Critical, "Fehlermeldung")
    4. Return
    5. End If
    6. If DataGridView1.SelectedRows.Count = 0 Then
    7. MsgBox("Löschen nicht möglich. Wählen Sie die zu löschenden Tabellendaten aus", MsgBoxStyle.Critical, "Fehlermeldung")
    8. Return
    9. End If
    10. If MsgBox("Eintrag löschen?", CType(MsgBoxStyle.Question + MsgBoxStyle.OkCancel, Global.Microsoft.VisualBasic.MsgBoxStyle), "Bestätigung") = MsgBoxResult.Cancel Then Return
    11. Try
    12. Connection.Open()
    13. Catch ex As Exception
    14. MessageBox.Show("Verbindung fehlgeschlagen !!!" & vbCrLf & "Bitte überprüfen Sie, ob der Server bereit ist !!!", "Fehlermeldung", MessageBoxButtons.OK, MessageBoxIcon.Error)
    15. Return
    16. End Try
    17. Try
    18. If AllCellsSelected(DataGridView1) = True Then
    19. MySQLCMD.CommandType = CommandType.Text
    20. MySQLCMD.CommandText = "DELETE FROM " & Table_Name
    21. MySQLCMD.Connection = Connection
    22. MySQLCMD.ExecuteNonQuery()
    23. End If
    24. For Each row As DataGridViewRow In DataGridView1.SelectedRows
    25. If row.Selected = True Then
    26. MySQLCMD.CommandType = CommandType.Text
    27. MySQLCMD.CommandText = "DELETE FROM " & Table_Name & " WHERE ID = '" & row.DataBoundItem(8) & "'"
    28. MySQLCMD.Connection = Connection
    29. MySQLCMD.ExecuteNonQuery()
    30. End If
    31. Next
    32. Catch ex As Exception
    33. MsgBox("Fehler beim Löschen" & vbCr & ex.Message, MsgBoxStyle.Critical, "Fehlermeldung")
    34. Connection.Close()
    35. End Try
    36. PictureBoxImagePreview.Image = Nothing
    37. Connection.Close()
    38. ShowData()
    39. End Sub


    DataBoundItem wird hier rot unterstrichen und folgender Fehler wird ausgegeben:

    BC30574:"Option Strict On" lässt spätes Binden nicht zu.

    Kann mir bitte jemand erklären was hier falsch ist bzw. wie es richtig wäre.

    Option Strict OFF funktioniert der Button Löschen einwandfrei.

    Danke und einen schönen Abend

    Gebhard
    Dann mach doch dieses Ding vom Typ Object zu dem, was es ist. Integer, String, whatever. Dafür gibt es Casts, z.B. CInt. Oder für zu-String extra die Funktion .ToString
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Hallo VaporiZed

    Habe ich schon versucht.

    VB.NET-Quellcode

    1. MySQLCMD.CommandText = "DELETE FROM " & Table_Name & " WHERE ID = '" & row.DataBoundItem.ToString(8) & "'"

    Dann ist der Fehler weg. ABER wenn ich einen Haltepunkt in dieser Zeile setze wird NICHT die ausgewählte ID gelöscht sonder es wird steht das in der Befehlszeile:

    MysQLCMD.CommandText "DELETE FROM tbl_Lager WHERE ID ='a'"

    Eigentlich sollte da die ID Nr. die in der DGV in der Spalte (8) steht stehen. MysQLCMD.CommandText "DELETE FROM tbl_Lager WHERE ID ='12447'"
    Bilder
    • Screenshot.jpg

      92,03 kB, 1.549×385, 85 mal angesehen
    Fast schon witzig. Aber nur fast. Du nimmst die String-Darstellung von DataBoundItem - was immer das dann auch ist - und davon das 9. Zeichen. Irgendwas.ToString -> Stringdarstellung von Irgendwas. Und davon Index 8 -> 9. Zeichen jener Textdarstellung, da EinString(8) eben das 9. Zeichen (da nullbasiert) wiedergibt.
    So ist's besser: row.DataBoundItem(8).ToString. Damit wird das 9. DataBoundItem genommen und eine Textversion davon wiedergegeben.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    VB.NET-Quellcode

    1. MySQLCMD.CommandText = "DELETE FROM " & Table_Name & " WHERE ID = '" & row.DataBoundItem(8).ToString & "'"


    habe ich als erstes genommen.

    Jetzt sagt vb.net bei Option Strict ON BC30574:"Option Strict On" lässt spätes Binden nicht zu

    und DataBoundItem ist mit einer roten wellenlinie unterstrichen
    Aha. Microsoft sagt, dass man über DataBoundItem an das Teil (in Object-Form) kommt, was in jener Zeile dargestellt wird. Daher klappt also row.DataBoundItem(8) nicht - weil ein 9. Element von einem Object nicht generell existiert. Caste also - wenn Du denn so arbeiten willst - das DataBoundItem zu dem Typ, was es tatsächlich ist und nimm die Property, die Du haben willst. Oder nimm (was aber schlimmer wär), den DGV-Inhalt. Wenn Du aber wissen willst, warum der Option Strict Off-Code ging, dann schau doch mal per Haltepunkt nach, was bei Option Strict Off in row.DataBoundItem drinsteckt und was Du bei row.DataBoundItem(8) dann rausbekommst.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Typhoon schrieb:

    und DataBoundItem ist mit einer roten wellenlinie unterstrichen

    Der Fehler bemängelt nicht row.DataBoundItem - weil diese Property gibts.
    Sondern er bemängelt den indizierten Zugriff, also dass du daran noch (8) angehängt hast, als sei der DatentTyp der Property ein Array, oder eine Liste.
    Die Property DataGridViewRow.DataBoundItem ist aber des Datentyps Object. Da kann also zur Laufzeit alles mögliche drinne sein (zB auch ein Array (isses aber nicht)).

    an dieser Stelle ist also wichtig, herauszubekommen, was für Objekte zur Laufzeit in row.DataBoundItem drinne sind. Es scheint ja ein indizierbares Objekt zu sein.
    Also Haltepunkt, und im LokalFenster den Datentyp nachgucken.

    Typhoon schrieb:

    row.DataBoundItem.ToString(8)
    Hast Du Dich davon überzeugt, dass da genau das drin steht, was drin stehen soll?
    Debuggen, Fehler finden und beseitigen
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Also ich greife immer bei DatagridviewRow mit der Cell-Eigenschaft auf Werte zu.

    Auszug aus einem Löschbefehl:

    VB.NET-Quellcode

    1. Dim dgvRow As DataGridViewRow = Nothing
    2. Dim delTask As New List(Of Integer)
    3. [...]
    4. For Each dgvRow In DGVTask.SelectedRows
    5. If dgvRow.Cells(GrdColTask.Desktop).Value = True Then myTask.ClosefrmDesktopTask(dgvRow.Cells(GrdColTask.EntryID).Value)
    6. delTask.Add(dgvRow.Cells(GrdColTask.EntryID).Value)
    7. Next
    8. [...]


    Gruß Achilleus
    Guten Morgen

    @RodFromGermany

    Ich habe einen Haltepunkt in der Zeile 167 gesetzt um zu prüfen was für ein Wert im CMD-Text steht. (Option Strict OFF) Bild 1

    Funktioniert und die Markierte Zeile wird aus der DB gelöscht.

    Option Strict ON wird der oben erwähnte Fehler angezeitg. Bild 2

    Bild 3 die ID ist in Spalte 8
    Bilder
    • Screenshot2.jpg

      115,3 kB, 1.396×325, 76 mal angesehen
    • Screenshot3.jpg

      105,29 kB, 1.699×328, 70 mal angesehen
    • Screenshot.jpg

      181,38 kB, 1.549×367, 71 mal angesehen
    Jetzt bist Du genau hier:

    VaporiZed schrieb:

    Oder nimm (was aber schlimmer wär) den DGV-Inhalt.
    Weil - um eine beliebte Formulierung von @ErfinderDesRades zu verwenden - Du jetzt in die Daten eines Controls reingrabschst, anstatt es richtig zu machen. Dein Bild#1 aus Post#10 zeigt nämlich sehr gut, was das eigentliche Ziel sein soll: Casten von DataBoundItem in den Zieltyp. Der ist dort nämlich angegeben: System.Data.DataRowView. Und das heißt für mich, dass Du da ein typisiertes (möge es typisiert sein!) DataSet hast und eine Tabelle in dem DGV darstellst. Und dann bist Du beim berühmt-berüchtigten Doppelcast, der Dir aus diesem allgemeinen und nicht verwendbaren Object plötzlich ein typsicheres Datenobjekt erzeugen kann, mit dem Du dann auf die Wunschproperty zugreifen kannst.
    Aber da sind wir wieder beim Thema: der einfache Weg führt zur dunklen Seite der Macht …
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Typhoon schrieb:

    Option Strict ON und die Markierte Zell wird aus der DB gelöscht
    Hm, ich denke das Ziel von Option Strict On ist vorwiegend Typen zu verstehen.
    Du hast nun auf diesem Weg keinen Option Strict On-Fehler behoben. Sondern die Datenabrufmethode geändert.

    Das ist also eher ein leidiger Zufall in diesem Anwendungsfall das trotz Änderung der angewandten Methode weiterhin dasselbe Ergebnis erzielt wird.^^

    Achilleus schrieb:

    Was ist daran so bös?


    Ich finds nicht böse, aber ich finde DataGrids/DataGridViews sind zur Ansicht, zum editieren von Datensätzen hab ich generell Dialoge, da geht alles über Bindung was ich schöner finde als direkt Zellwerte zu nutzen. Was wenn eine Column hinzukommt oder wegfällt? Dann passt bei dir u.U. der Index nicht mehr, bei Bindung hat man das einfacher.
    PS:
    Zudem ist DataGridViewCell.Value vom Typ Object, verwendet man in Forms ein typisiertes DataSet und bindet alles, spart man sich sogar die herumcasterei.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

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

    @Achilleus
    Der Einwand meinerseits besteht nicht an der Methode generell, sondern daran, dass das nicht wirklich besser ist als das einfach Option Strict Off zu lassen, denn das würde ja auch funktionieren.
    Wieso will der TE Option Strict verwenden?
    Mit deiner Lösung lautet die Antwort doch eindeutig: Weil das irgendwer gesagt hat.
    Mit der anderen Lösung kann die Antwort hingegen lauten: Weil das einen weiterführenden Sinn hat.

    Aufgrund der Probleme die DTF anspricht muss man sogar sagen, wäre ja sogar Option Strict Off noch zu bevorzugen. Das Castet der von allein und da kommt nix im Binding durcheinander.

    Haudruferzappeltnoch schrieb:

    wäre ja sogar Option Strict Off noch zu bevorzugen.


    Sehe ich anders. OS-Off ist einfach nur einfacher für die, die sich nicht mit Typen auseinander gesetzt haben, bzw. es nicht wollen, oder die Risiken noch nicht kennen oder es ihnen trotzdem egal ist, weil es für den Moment funktioniert. Ich war auch so einer, hab sehr spät eingesehen das On besser ist, hatte wegen Off immer wieder mal überraschungen zur Laufzeit. Bei Off hat man schneller Laufzeitfehler als mit On. Ich finde das sollte in VB genau wie in C# sein, kein OS-Off möglich.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Achilleus schrieb:

    Das Datagridview ist doch genau dafür da, die Daten visuell darzustellen. Warum soll ich nicht auch darauf zugreifen?
    Was ist daran so bös?
    man hat halt deutlich mehr Möglichkeiten, wenn man mit den Daten arbeitet, und nicht mit iwelchen Control-Properties.
    Den Weg, der Typhoon nu eingeschlagen hat, verunmöglicht ihm, eine sinnvolle Datenmodellierung überhaupt zu erlernen.
    ZB, im Bild-Anhang aus post#3 sehe ich, dass er mit nicht ausnormalisierten Tabellen hantiert.
    Nämlich hätte er ein Datenmodell nach Stand der Technik zugrundeliegen, so wären die Spalten 120mm, 125mm, 160mm ausnormalisiert und in einer einzigen Column verfügbar gemacht, nämlich eine ComboboxDataGridviewColumn.
    Also es gäbe statt der drei Spalten nur eine (vielleicht des Namens "t [mm]"), und zwar mit Comboboxen im Dgv, und jede Combo in dieser Spalte würde genau die Werte 120, 125, 160 zur Auswahl anbieten und nix anneres.
    Ebenso verhält es sich mit den Spalten ohneEinstich, 18mmEinstich, 25mmEinstich - da käme eine ComboboxColumn "Einstich" inFrage, mit den Optionen ohne, 18mm, 25mm.

    Jo, wenn man mit Control-Properties arbeitet, statt mit den Daten des Datenmodells, dann ist natürlich ausgeschlossen, dass man Datenmodellierung und Databinding überhaupt erlernt...
    Und das ist sehr schade, weil mit einem typDataset liegt ein typisiertes Datenmodell eiglich vor - man müsste es nur benutzen...

    Aber vmtl. wisst ihr beide garnet so recht, wovon ich ühaupt rede. Bei Interesse vlt. im Datenbank-Tut-Bereich "die relationale GrundIdee" nachlesen oder sowas...
    Jdfs. nicht-triviale Datenverarbeitungs-Anwendungen zu entwickeln scheint mir ohne derlei Basics ziemlich aussichtslos.
    (aber vlt. bin ich auch selbst betriebsblind. Wer einen Hammer hat, für den sieht die Welt aus wie ein Nagel - ich seh alles durch die relationale Brille)



    Jo - strenggenommen führt das bisserl vom Ursprungs-Thema "Strict On" weg.
    Oder vlt auch nicht, weil mit einem typ Datenmodell arbeitet man natürlich Strict On, und bis hin zu post#8 ging es auch darum, die DgvRow.DataboundItem-Objekte auf den richtigen Datenmodell-Typ zu casten (den wir hier nicht kennen - dazu müssten wir Screenshot sehen vom Dataset (*.xsd).
    Aber wenn man mit dgv.Cells(8).Value.ToString() anfängt isses vorbei.
    Da kennt man kein Datenmodell mehr - da gibts nurnoch Strings.

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