Typisiertes Dataset als ByRef an Sub übergeben

  • VB.NET

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von Vatter.

    Typisiertes Dataset als ByRef an Sub übergeben

    Hallo liebe Leuts,
    ich wollte mein Dataset mit einer Extension versehen, die es mir erlaubt wie mit ReadXML/WriteXML ein typisiertes Dataset als GZip zu speichern. Dabei bekam ich folgende Fehlermeldung: "Fehler 2 "Option Strict On" lässt das Einschränken von Typ "System.Data.DataSet" zu Typ "GeraetePruefung.DS" beim Zurückkopieren des ByRef-Parameterwerts "MyDAtaset" in das entsprechende Argument nicht zu. C:\Users\...\MainFrm.vb 76 17 GeraetePruefung"
    Um das zu testen, hab ich folgenden einfachen Code verwendet:

    VB.NET-Quellcode

    1. Sub Laden()
    2. Reload(DS, DateiName)
    3. End Sub
    4. Private Sub Reload(ByRef d As DataSet, Datei As FileInfo)
    5. d.ReadXml(Datei.FullName)
    6. End Sub

    Die Fehlermeldung war die selbe. Es schein also nicht möglich zu sein, ein einfach eingelesenes Dataset in ein typisiertes zu stopfen. Auch Versuche mit einer Funktion, die das eingelesene Dataset zurück gibt und dann Wandlung mit CType schlugen fehl.
    Hat jemand ne Idee, wie ich das bewerkstelligen könnte? Ich würde das gern über eine Extension-Methode machen, damit mein Formcode damit nicht so vollgestpoft wird und die Funktion wiederverwendbar wird.

    MfG

    Vatter
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:
    Bei der Extension für die Dataset-Klasse schon, oder? Extension erfordern als ersten Parameter die zu erweiternde Klasse als ByRef.
    Speichern hab ich in einem Modul einer Klassenbibo wie folgt, was auch supi funzt:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. <Extension()> _
    2. Public Sub Save_GZip(ByVal MyDataset As DataSet, Fi As FileInfo)
    3. _save_GZip(MyDataset, "", Fi.FullName, 1024)
    4. End Sub
    5. Private Sub _save_GZip(ByVal DS As DataSet, ByVal Name As String, ByVal ZielPfad As String, ByVal PufferSize As Integer)
    6. Dim _zielpfad As String = ZielPfad
    7. Dim _puffer As Integer = PufferSize
    8. 'Aufruf eines Savfiledialogs, wenn kein Pfad vorgegeben wurde
    9. If _zielpfad = "" Then
    10. Using sfd As New SaveFileDialog
    11. sfd.Filter = "GZip-DateInterval *.gz|*.gz"
    12. sfd.FileName = Name
    13. sfd.Title = Name
    14. If sfd.ShowDialog = DialogResult.OK Then
    15. _zielpfad = sfd.FileName
    16. Else
    17. 'Abbruchbedingung
    18. Exit Sub
    19. End If
    20. End Using
    21. End If
    22. 'Memory-Stream erzeugen
    23. Using ms As New MemoryStream
    24. DS.WriteXml(ms) 'Tabelle in MS schreiben
    25. ms.Seek(0, SeekOrigin.Begin) 'ms Position zurücksetzen
    26. Using zielStream As New FileStream(_zielpfad, FileMode.Create)
    27. Using zipStream As New GZipStream(zielStream, CompressionMode.Compress)
    28. 'Puffer
    29. Dim Puffer(PufferSize - 1) As Byte
    30. 'Kopier-Schleife
    31. Do
    32. PufferSize = ms.Read(Puffer, 0, PufferSize)
    33. zipStream.Write(Puffer, 0, PufferSize)
    34. 'Schleife endet, wenn der Puffer nicht ganz befüllt wurde
    35. Loop Until PufferSize < Puffer.Length
    36. Debug.WriteLine("Dataset im Memorystream: " & ms.Length.ToString & "Byte | Gzip: " & zielStream.Length.ToString & "Byte")
    37. End Using
    38. End Using
    39. End Using
    40. End Sub
    Der Aufruf erfolgt nun einfach mit:

    VB.NET-Quellcode

    1. MyDataset.SaveGzip(MyFileinfo)


    Umgekehrt mit dem Lesen gehts dann aus besagtem Grund nicht:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. <Extension()> _
    2. Public Sub ReadGzip(ByRef MyDAtaset As DataSet, ByVal QuellPfad As FileInfo)
    3. MyDAtaset = _readGZip("", QuellPfad.FullName)
    4. End Sub
    5. Private Function _readGZip(Name As String, ByVal QuellPfad As String) As DataSet
    6. Dim _quellpfad As String = QuellPfad
    7. Dim ds As New DataSet
    8. 'Aufruf eines Savfiledialogs, wenn kein Pfad vorgegeben wurde
    9. If _quellpfad = "" Then
    10. Using sfd As New OpenFileDialog
    11. sfd.Filter = "GZip-DateInterval *.gz|*.gz"
    12. sfd.FileName = Name
    13. sfd.Title = Name
    14. If sfd.ShowDialog = DialogResult.OK Then
    15. _quellpfad = sfd.FileName
    16. Else
    17. 'Abbruchbedingung
    18. Return Nothing
    19. End If
    20. End Using
    21. ElseIf Not File.Exists(_quellpfad) Then
    22. MessageBox.Show("Die zu entpackende datei existiert nicht oder der angegebene Pfad ist ungültig")
    23. Return Nothing
    24. End If
    25. ' Rück-Konvertierung. Beachte, daß hier der GZipStream auf dem quell-
    26. ' Stream aufsitzt, und mit CompressionMode.Decompress erstellt ist.
    27. Using _quellStream As New FileStream(_quellpfad, FileMode.Open), _
    28. unZipStream As New GZipStream(_quellStream, CompressionMode.Decompress)
    29. Using ms As New MemoryStream 'MemoryStream als Zwischenspeicher
    30. 'Verwendung der in die Extension-Methode ausgelagerten Kopier-
    31. 'Schleife
    32. unZipStream.WriteTo(ms)
    33. ' Debug.WriteLine("Tabelle im ms: " & ms.Length.ToString & "Byte")
    34. 'Memoristream an Startposition setzen
    35. ms.Position = 0
    36. ds.ReadXml(ms) 'Tabelle aus Memorystream lesen
    37. End Using
    38. End Using
    39. Return ds
    40. End Function

    Ich habe jetzt den Code lokal mit reingenommen und eben ds durch die lokale Instanz des typisierten Dataset ersetzt. Das geht natürlerich.
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:
    mir scheint, du versuchst, über den ByRef-Parameter ein MyDataset quasi "zurückzugeben"
    Das ist üblicherweise keine gute Idee.

    Besser wärs, du würdest das (byval) gegebene Dataset einfach nur befüllen, mittels .ReadXml(Stream).

    Merke: ByRef ist üblicherweise immer nixgutt idee, nur wenn eine Methode mehrere Rückgabewerte haben soll, kommt man nicht drumrum.
    Grad in VB,, wo die Parameter-Angabe vonne Syntax her nicht unterscheidet zw. ByVal und ByRef.
    Aber es ist tatsächlich ein Heiden-Unterschied, obs hinterher noch dasselbe Dataset ist, oder ein anderes.

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

    MMMM,
    ich hab jetzt eigentlich alles mögliche ausprobiert, auch mit Byval. Selbst eine Funktion, die nur mit ReadXML arbeitet und das Dataset zurückgubt, mit CType gewandelt usw. bringt nischt. IDE sagt: typisiertes Dataset (Gerätedataset) kann nicht in Dataset gewindelt werden. :(
    Kann ich einer Funktion nicht den Typ als solchen mitgeben? dann könntich Dataset as bla deklarieren und im richtigen Typ zurückgeben. (vielleicht)
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:
    inne DbExtension-Download ist ja auch sone Load-Methode dabei, nur ohne OpenFielDialog, und ohne GZip.

    Also die geht im großen uind ganzen so:

    VB.NET-Quellcode

    1. <Extension()> _
    2. Public Function LoadXml(ByVal dts As DataSet) As DataSet
    3. DirectCast(dts.Attach, DatasetXmlAdapter).Fill()
    4. Return dts
    5. End Function

    Wobei der Rückgabewert egal ist - der gibt ja nur das Argument selbst wieder zurück.

    Also

    VB.NET-Quellcode

    1. <Extension()> _
    2. Public Sub LoadXml(ByVal dts As DataSet, fileName as string)
    3. dts.ReadXml(fileName)
    4. End Function
    ist sicher problemlos möglich, und wenn du statt des .ReadXml da was eigenes implementierst, solltedas doch laufen.

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

    Oh Gott,
    ich Trollo. Da probiert man die abwegigsten Sachen, und denn is die einfachste Lösung di wo funktioniert.
    Ich habe den Fehler gemacht, mehrere Überladungen zu erstellen, die dann 1 Funktion aufrufen, die "alles" kann, um redundanten Code zu vermeiden. Und genau diese Rückgabe zur Extension-Sub hat dann alles durcheinandergewuselt, da hier ein untypisiertes Dataset in ein typisiertes gequält werden sollte.
    Nun hab ich beschlossen, dass mich in der Erweiterung der redundante Code wenig stört, so.

    Nun gehts prima,
    Danke EDR
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup: