Zugriff auf ein typisiertes DataSet im Code

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

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

    Zugriff auf ein typisiertes DataSet im Code

    Hallo,

    ich habe ein typisiertes Dataset aus einer XSD-Datei erstellen lassen, welches ich zum Importieren von schemakonformen XML-Dateien benutze. Nach dem Import möchte ich im Code auf dieses Import-DataSet zugreifen, um Daten in ein anderes DataSet zu kopieren, meine eigentliche Datenbank. Dabei tauchen mehrere Probleme auf. Um zu sehen, welche Eigenschaften und Methoden die einzelnen Tabellen-Klassen haben, hilft mir der ObjektBrowser (F2). Damit konnte ich schon folgendes "Problem" lösen:

    VB.NET-Quellcode

    1. Dim ICaRow As ICaDataSet.ICaRow
    2. ICaRow = CType(ICaDataSet.ICa.NewRow(), ICaDataSet.ICaRow)
    3. ' Wieso muss ich hier casten? ICaDataSet.ICa.NewRow() müsste doch eine ICaDataSet.ICaRow liefern.
    4. ' Oha, wie peinlich. Ich hab es gefunden:
    5. ICaRow = ICaDataSet.ICa.NewICaRow


    Das ist das Import-Dataset:
    und das die Datenbank:

    Nun möchte ich auf die Daten einer bestimmten Row zugreifen. Ich weiß, dass in der Tabelle nur eine Zeile vorhanden ist und möchte also Row(0) und davon die Column bzw. das Feld "SE" haben:

    VB.NET-Quellcode

    1. Dim metadataRow As ICaDataSet.metadataRow
    2. metadataRow = ICaDataSet.metadata.NewmetadataRow
    3. metadataRow.SE = CType(DataSetDS02.Tables("DS02_data").Rows(0)("SE"), String)


    Das funktioniert zwar, sieht aber im Sinne von typisierter Programmierung falsch aus.

    VB.NET-Quellcode

    1. metadataRow.SE = DataSetDS02.DS02_dataDataTable.Item(0).SE


    Der Compiler sagt dazu: "Der Verweis auf einen nicht freigegebenen Member erfordert einen Objektverweis". Das verstehe ich leider nicht, also ich weiß nicht, was ich jetzt machen soll. Ist .Item(0) kein Objekt? Ich versuche es mal mit .Select() und weil das eine untypisierte DataRow liefert, mit DirectCast:

    VB.NET-Quellcode

    1. Dim DS02_DataRows() As DataSetDS02.DS02_dataRow
    2. DS02_DataRows = DirectCast(DataSetDS02.DS02_data.Select(), DataSetDS02.DS02_dataDataTable)


    Fehler: "Der Wert vom Typ "DataRow()" kann nicht in "DataSetDS02.DS02_dataDataTable" konvertiert werden."

    Boaahh, ich dreh noch durch und sehe vor lauter Bäumen den Wald nicht mehr. Könnte mir bitte jemand auf die Sprünge helfen? Das kann doch nicht so schwierig sein.
    Danke.

    Viele Grüße,
    Oliver
    Ich kann Dir bei deinem Problem leider nicht wirklich helfen weil ich slbst noch nicht soweit bin.
    Allerdings....

    OliverSte schrieb:

    metadataRow.SE = CType(DataSetDS02.Tables("DS02_data").Rows(0)("SE"), String)

    ist kein typisierter Zugriff. Das wird dir @ErfinderDesRades vermutlich auch sagen.
    Da Du schon den ObjectBrowser erwähnst...schau da mal nach was Dir alles angeboten wird.

    Zitat aus EdR´s Tutorial
    ​ Don't fall back into Codesmells like


    Dim tbOrder = OrderDts.Tables("Order")
    Rechtschreibfehler betonen den künstlerischen Charakter des Autors.
    @OliverSte Vom DataSet-Designer wird Dir doch ein Konstruktor für Deine DataTable generiert, den musst Du einfach aufrufen:

    VB.NET-Quellcode

    1. _DataTable = New MyProject.DataSet1.DataTableDatumDataTable()
    und feddich.
    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!

    Akanel schrieb:


    Allerdings....

    OliverSte schrieb:

    metadataRow.SE = CType(DataSetDS02.Tables("DS02_data").Rows(0)("SE"), String)

    ist kein typisierter Zugriff. Das wird dir @ErfinderDesRades vermutlich auch sagen.
    Da Du schon den ObjectBrowser erwähnst...schau da mal nach was Dir alles angeboten wird.


    Nicht hilfreich.
    Dass es sich hier um untypisierten Mist handelt, habe ich doch selbst gesagt. Ich möchte es ja gern richtig machen
    Und der ObjektBrowser hilft mir dabei nicht, "ich sehe vor lauter Bäumen ...", hatte ich auch bereits gesagt.


    @RodFromGermany
    Leider auch nicht hilfreich. Vielleicht habe ich nicht genug Informationen mitgeteilt?
    Es gibt schon ein Objekt (!) DataSetDS02 von diesem Typ und das DataSet ist auch bereits gefüllt.
    Die Frage ist, wie greife ich auf Zeilen von Tabellen zu?
    Das DataSet-Objekt ist DataSetDS02, die Tabelle DS02_data, sie enthält genau einen Datensatz.

    Dennoch danke für Eure Bemühungen ;)

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

    @OliverSte So was "s2" ist der Name der Spalte:

    VB.NET-Quellcode

    1. table.Rows(2).Item("s2") = "bla"

    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!
    Ja mein lieber @ErfinderDesRades, genau so geht das.
    Wie es da so steht, sieht's einfach und klar aus. Aber ich habe es nicht gefunden, seit Tagen ...

    Vielen Dank! Ich freue mich wirklich sehr über den ganz ordinären Hinweis.


    jo, das ist der Unterschied zum typisierten Programmieren.
    Ich empfehle dir sehr dieses Tut:
    codeproject.com/Articles/10351…ped-Dataset-for-Beginners
    Aber ich glaube fast, das kennste schon.
    Vlt. nochmal, gründlich durchlesen.

    Kernaussage ist: Wenn eines der 3 Worte: DataRow, Dataset, DataTable in deim Code auftaucht, dann machste was falsch, weil haste die typisierte Schiene verlassen und fängst zu Wursteln an.
    Mach einfach mal Volltextsuche in deim Code nach diesen 3 Worten - das führt dich von einer "Problemzone" zur nächsten.
    (Aber hab ich grad mit "Datarow" gemacht - so viel schlimmes ist das garnet :thumbsup: )
    @ErfinderDesRades hab ich total kapiert, also das mit den drei Worten und möchte das auch dringend richtig machen. Es fällt mir nur schwer ...

    Weil .Select() eine untypisierte DataRow zurückliefert, dachte ich, ein Cast wäre die Lösung. Aber warum geht das hier nicht:

    VB.NET-Quellcode

    1. Dim rwsICa() As ICaRow
    2. rwsICa = DirectCast(ICaDataSet.ICa.Select("kommNr= '" & rwDS02.kommNr & "' AND zeitraum=" & zeitraum.ToString), ICaRow)


    Also mache ich es so:

    VB.NET-Quellcode

    1. Dim rwsDataRow() As Data.DataRow
    2. rwsDataRow = ICaDataSet.ICa.Select("kommNr= '" & rwDS02.kommNr & "' AND zeitraum=" & zeitraum.ToString)


    Und schon habe ich ein böses Wort benutzt (DataRow).
    Im ObjectBrowser finde ich aber nichts typisiertes mit Find oder Select auf einer meiner Tables zum Abfragen von bestimmten Datensätzen. Gibt es da nichts oder suche ich an der falschen Stelle?
    Du willst anscheinend einige bestimmte DataRows aus der Tabelle fischen. Das liefe über LINQ mit Where() statt Select() - falls Du das IntelliSense-unterstützte LINQ denn verwenden willst:

    VB.NET-Quellcode

    1. Dim rwsICa = ICaDataSet.ICa.Where(Function(x) x.kommNr = rwDS02.kommNr AndAlso x.zeitraum = zeitraum.ToString)

    Beim Eintippen erhältst Du von der IDE Eingabevorschläge, da sie in die DataSets quasi reinschauen kann, und Du bekommst ein Array streng-typisierter Rows zurück. Wie gewünscht.
    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.

    OliverSte schrieb:

    Weil .Select() eine untypisierte DataRow zurückliefert...
    DataTable.Select() ist eben auch böse.
    Gibt auch keinen Grund, es zu verwenden - siehe VaporiZeds Post: Linq ist viel mächtiger, und typsicher ausserdem.

    Problematisch finde ich nur deine Variable zeitraum As String.
    Zeiträume lassen sich sicher besser abbilden als als String.

    ErfinderDesRades schrieb:

    DataTable.Select() ist eben auch böse.


    Ja, die Vermutung hatte ich, sieht ja auch gecoded schon ziemlich gekotet aus ;)
    Das mit .where muss man erst drauf kommen, klasse. Dann will ich mich mal mit Linq auseinandersetzen ... Ich glaube, dazu gibt's hier sogar ein Tut.
    Danke Leute!

    @ErfinderDesRades Der Name der Variablen "zeitraum" ist für Aussenstehende irreführend, denn es sie enthält nur eine Jahreszahl und steht für den Zeitraum eben dieses Jahres. "JahrDesAbgleichs" wäre eine treffende Bezeichnung. Ich habe das mal nach Short geändert, sowohl im Datenmodell, als auch im Code, dann muss ich nicht immer herumcasten.

    Eine Frage noch zum .Where. Die Rückgabe ist kein Array, sondern "Sequenz von Zeilen auf Grundlage des angegebenen Prädikats". Wie Deklariere ich sowas, oder mach ich nach Gebrauch einfach

    VB.NET-Quellcode

    1. rwsICa=nothing

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

    Falls Du wirklich ein Array brauchen solltest, kannst Du am Ende der Where-Zeile folgendes ergänzen: .ToArray(). Dann kommt auch eines raus. Allerdings beraubt es Dir die Möglichkeit mit LINQ weiterzumachen. Denn an die Where-Zeile kann ans Ende auch noch eine weitere LINQ-Sache, z.B. Where-Einschänkung (wär n bisken planlos, aber es geht ums Prinzip). Oder ein Select. Oder OrderBy. Eben sämtliche LINQ-Anweisungen, um eventuelle "Filter" noch weiter zu verfeinern. Und zum Schluss kann man auch ToList() schreiben, um dann eben eine List(Of TypisierteDataRow) zu bekommen, falls man gerne mit so etwas arbeitet.
    Eine Typangabe bei der Variablendeklaration ist eigentlich mit Option Infer überflüssig, aber IntelliSense würde Dir bei einer korrekten LINQ-Zeile eh zeigen, was bei Deiner Abfrage rauskommt:


    EDIT:

    OliverSte schrieb:

    oder mach ich nach Gebrauch einfach rwsICa=Nothing
    Kannst Du. Musst Du nicht. Wird ja eh entsorgt, sobald das Programm den lokalen Block verlässt. rwsICa ist ja nur eine weitere temporäre/lokale Variable.
    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.

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

    OliverSte schrieb:

    Dann will ich mich mal mit Linq auseinandersetzen ...
    Jo - dassis überaus empfehlenswert! :thumbsup:

    OliverSte schrieb:

    .. Ich glaube, dazu gibt's hier sogar ein Tut.
    Echt? - nicht dassich wüsste.

    Ich fund aber damals viele gute Quellen im INet, v.a. MSDN. - zumindest ich konnte die Beispiele gut gebrauchen.
    Ein wirkliches Tut dazu stell ich mir sehr schwer zu schreiben vor, weil bei Linq fließt alles zusammen:
    Type-Inference, Extension-Methods, Generica, Delegaten, anonyme Methoden, Interfaces,...

    Und im Ergebnis kommt dann diese verblüffend intuitive Abfragesprache für Auflistungen aller Art heraus.
    @VaporiZed Ich nutze die Variable inner Schleife häufiger. Daher mache ich das jetzt mit =nothing bevor ich neu Dimme.

    @ErfinderDesRades Das hier nennt sich jedenfalls Tut, obs eins ist, muss ich noch herausfinden.
    Du selbst hast auch mal was interessantes dazu verfasst.

    Diese beiden Threads hatte ich adressiert ;)
    Also das erste Tut hat ja einige Mängel, ist ja dort auch angesprochen (und ich wüsste noch weitere).
    Ein wichtiger Mangel ist auch, dasses im falschen Tut-Bereich liegt - weil Linq hat mit Datenbanken ühaupt nix zu tun. Deswegen habich das Tut auch nicht gefunden - ich hab natürlich in "Allgemein" gesucht.
    Das kann man ja beheben - werd ich die Mods mal drauf anfragen.

    Mein eigenes Tut hingegen ist im Db-Bereich ganz richtig, weil es behandelt ein ganz spezielles SpezialFeature der System.Data.DatasetExtensions - Bibliothek.

    Aber Linq ist noch viel mehr - also für eine Ahnung zu kriegen ist erstes Tut nicht verkehrt.
    Allerdings denke ich fast, wenn man im ObjectBrowser sich die Methoden der Linq.Enumerable-Klasse anguckt, und dann mit F1 immer inne Msdn hopft, hat man dieselbe Info vlt. fundierter.

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