DataSet only - Datarow kopieren, mit Form und möglichen Useränderungen

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

Es gibt 33 Antworten in diesem Thema. Der letzte Beitrag () ist von VB1963.

    DerSmurf schrieb:

    zwei dlls [...], die zusammen 350Kb groß sind, obwohl sie eigentlich nur 50Kb (natürlich geraten) groß sein müssten.
    Den Größen-Vergleich kapier ich nicht. Wie kommst Du auf Deine geratene Dateigröße? Warum müssten sie 50KB groß sein? Vergleichst Du gerade VB-Datei mit DLL-Datei?
    Spielt Größe eine Rolle? stackoverflow meint: Nein. Ich sage: für die Laufzeitperformance weiß ich es nicht, aber ich denke nicht. Ausprobieren. Aber auch da ist natürlich die Sache, dass die Voll-DLL im Vergleich zu Deiner diuretischen Teil-Code-DLL natürlich nicht 10000x so groß ist. Von daher wird man - falls überhaupt ein Unterschied da sein sollte - nix spüren. Trotzdem: Ich denke, dass es in der Natur einer DLL liegt, dass da zur Laufzeit eben kein Unterschied sein sollte. Zur Designzeit muss natürlich der Compiler erstmal alle Verweise, die in der DLL zur Verfügung stehen, laden, damit man sieht, was alles in der DLL öffnetlich zur Verfügung steht. Und wenn man zur Laufzeit mit Reflection an ne DLL rangeht, könnte es auch noch leichte Unterschiede geben, aber im Normalfall tippe ich auf: irrelevant.
    Aber: Alles Spekulatius.
    Für das Versenden per Mail oder so: natürlich. Ob Du jetzt ne 30-KB-DLL weitergibst oder ne 30-MB-Datei, macht schon einen Unterschied, klar. Aber letzteres war ja nicht die Frage.
    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 1 mal editiert, zuletzt von „VaporiZed“ ()

    Die 50kg waren einfach geraten.
    Die importierte dll wird ja einfach kleiner, wenn ich Code lösche, den ich nicht brauche.
    Wenn es für die Laufzeitperformance keine Rolle spielt - klatsche ich die beiden dlls an mein Projekt, und höre auf mir darüber Gedanken zu machen.
    Denn ob ich nun ein halbes MB mehr oder weniger weitergebe, spielt ja heutzutage auch irgendwie keine Rolle.
    In deinem Link steht zwar, dass eine größere dll besser sei, als zwei kleine.
    Aber das spielt glaube ich in meinem Projekt hier auch keine echte Rolle.
    Also ich fändes auch nicht soo toll, nur für dieses eine Feature meine kompletten doch recht umfangreichen Helper-Bibliotheken-Sources einzubinden.
    Deshalb habich ja damals die "HelpersSmallEd" daraus quasi extrahiert.
    Man könnte nun die TupleList und die zusätzliche EditNew-Überladung ebenfalls in die HelpersSmallEd überführen - das wär schon schlanker.

    Wobei - die TupleList braucht man ja nichtmal, du kannst dir auch eine normale List(Of Tuple(Of DataColumn, Object)) anlegen und befüllen - kannste auch an die EditNew-Überladung übergeben.
    Jo, mach das doch: Kopier die EditNew-Überladung zu die anneren EditNews innne HelpersSmallEd, und übergib eine klassische List(Of Tuple(Of DataColumn, Object)) anstelle meiner TupleList(Of DataColumn, Object)

    Annererseits tun die grossen HelpersProjekte ja tatsächlich nicht weh.
    Und wenn du noch mehr Projekte anfängst, kannstese da ja auch wahrscheinlich nutzbringend einbinden.
    Und immer viel fragen, weil kann wohl immer wieder mal passieren, dass dir noch annere Probleme aufkommen, die da eiglich schon gelöst sind.
    Ja, warum einfach, wenn es auch kompliziert geht...
    Die Übergabe der Tuple, habe ich hinbekommen. Erstmal nur mit Strings als Übergabeparameter, aber anstelle des Strings, kann ich ja übergeben, was ich will.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub BTNCopyArticle_Click(sender As Object, e As EventArgs) Handles BTNCopyArticle.Click
    2. Dim tpls As New List(Of Tuple(Of DataColumn, Object))
    3. With Articles.Article
    4. tpls.Add(Tuple.Create(Of DataColumn, Object)(.Name1Column, "Name1"))
    5. tpls.Add(Tuple.Create(Of DataColumn, Object)(.Name2Column, "Name2"))
    6. ArticleBindingSource.EditNew(Of frmEditArticle)(tpls)
    7. End With
    8. End Sub


    Das ändern der HelpersSmallEd war etwas komplizierter.
    Ich habe die EditNew Sub eingefügt. Zusätzlich zur bereits enthaltenen EditNew Sub.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. <Extension()>
    2. Public Function EditNew(Of T As {Form, New})(bs As BindingSource, defaultValues As List(Of Tuple(Of DataColumn, Object)), Optional owner As Form = Nothing, Optional onErrorRetry As Boolean = False) As DialogResult
    3. Dim drv = DirectCast(bs.AddNew, DataRowView)
    4. defaultValues.ForEach(Sub(tpl) drv(tpl.Item1.ColumnName) = tpl.Item2)
    5. Return EditItem(Of T)(bs, drv, onErrorRetry, owner)
    6. End Function
    7. ''' <summary> editiert bs.Current im angegebenen Dialog-Form. </summary>
    8. <Extension()>
    9. Public Function EditNew(Of TEditForm As {Form, New})(bs As BindingSource, Optional onErrorRetry As Boolean = False, Optional owner As Form = Nothing) As DialogResult
    10. Return EditItem(Of TEditForm)(bs, bs.AddNew, onErrorRetry, owner)
    11. End Function

    Das ist in deinem Demoprojekt auch so. Aber warum habe ich zwei Subs mit gleichem Namen?
    Ich kann mir doch die zweite sparen?

    Danach habe ich die EditItem Sub ändern müssen, wegen der zusätzlich übergebenen Parameter.
    Dann habe ich die Sub MoveToRow eingefügt, hierauf verweist die neue EditItem, und die gabs nicht.
    Und die EditNew (die "alte") und EditCurrent habe ich geändert.

    Insgesamt scheint alles zu laufen. Aber es wäre ein Traum, wenn du da mal drüberschaust, wenn Zeit ist.
    Habe sorge bei meiner Änderung zuviel / was falsches geändert zu haben, was erst später auffällt.
    Dateien
    Jo, sieht doch gut aus.
    Also ich habs nicht laufen lassen, davon geh ich aus, dasses funzt.

    Jo, das gibts halt, dass man mehrere Methoden mit demselben Namen hat. Sowas nennt man Überladung.
    Die machen halt dasselbe, nur eben auf unterschiedliche Weise: das eine EditNew braucht und verarbeitet defaultValues, das annere nicht.

    Ich kann mir doch die zweite sparen?
    Hihi - Probiers aus - wirste dann schon sehen, dass keine davon eingespart werden kann.
    Also streng genommen kannste dir das EditNew ohne DefaultValues sparen - dann musste aber immer, wennde EditNew machen willst, eine leere TupleListe mitgeben - das wär schon extrem hässlich.
    Jo, und dafür gibts halt Überladungen, dass man das schöner lösen kann.

    gugge auch Grundlagen: Fachbegriffe

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

    So meine lieben.
    Ich muss den Thread nochmal aufgreifen, denn ich habe zwei Probleme.
    Vorab der Code:

    VB.NET-Quellcode

    1. Private Sub BTNCopyArticle_Click(sender As Object, e As EventArgs) Handles BTNCopyArticle.Click
    2. 'Daten des aktuell ausgewählten Artikels auslesen
    3. If ArticleBindingSource.Current Is Nothing Then Exit Sub
    4. Dim SelectedArticle = DirectCast(DirectCast(ArticleBindingSource.Current, DataRowView).Row, DtsArticles.ArticleRow)
    5. 'Artikelnummer um eins erhöhen
    6. Dim ArtNr As String = IncreaseArtNr(SelectedArticle.ArtNr)
    7. 'zu dieser Function später mehr (Problem Nr2)
    8. 'Daten des Artikels an bearbeitenForm übergeben
    9. Dim tpls As New List(Of Tuple(Of DataColumn, Object))
    10. With DtsArticles.Article
    11. tpls.Add(Tuple.Create(Of DataColumn, Object)(.ArtNrColumn, ArtNr))
    12. tpls.Add(Tuple.Create(Of DataColumn, Object)(.Name1Column, SelectedArticle.Name1))
    13. 'ich übergebe noch mehr, aber das habe ich einfach mal gelöscht
    14. ArticleBindingSource.EditNew(Of frmEditArticle)(tpls)
    15. End With
    16. End Sub

    1. Wenn ein Wert, den ich in meiner List(Of Tuples) übergebe DNULL ist, schmiert das Programm ab, mit dem Fehler:
    System.Data.StrongTypingException: "Der Wert für Spalte Name1in Tabelle Article ist DBNull."
    InvalidCastException: Ungültige Konvertierung von Typ DBNull in Typ String.

    Also habe ich die Variable Name1 as string erzeugt und übergebe diese.
    Nun muss ich ja noch prüfen, ob der Wert in SelectedArticle.Name1 DBNull ist, aber das bekomme ich nicht hin.
    Ich habe zwar einige Wege mit google gefunden, aber es kommt immer der gleiche Fehler.

    VB.NET-Quellcode

    1. Dim name1 as string
    2. If not isdbnull(selectedArticle.Name1) then Name1 = SelectedArticle.Name1

    Wie muss diese "isdbnull" Abfrage richtig aussehen?

    2 Meine Funktion zum erhöhen der Artikelnummer:
    Wenn ich einen Artikel kopiere, möchte ich, dass die Artikelnummer um eins erhöht wird. Wenn die ArtNr nicht numerisch ist, soll eine 1 angehängt werden.
    Also aus der Nummer 123 soll 124 werden, aus 1d24 soll 1d25 werden.
    Das habe ich mit folgendem Code bewerkstelligt, welcher auch seinen Dienst tut.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Function increaseArtNR(ArtNr As String) As String
    2. Dim Number As Integer
    3. Dim i As Integer
    4. Dim NewArtNr As String
    5. 'Wenn Artikelnummer numerisch ist, um eins erhöhen und zurückgeben
    6. If Integer.TryParse(ArtNr, Number) Then
    7. NewArtNr = (Number + 1).ToString
    8. Else
    9. 'ArtNr von hinten nach vorne durchlaufen und Zahl auslesen
    10. Dim Tempnumber As Integer
    11. Dim ArtNrLenght As Integer = ArtNr.Length
    12. For i = 1 To ArtNr.Length
    13. Number = Tempnumber
    14. If Not Integer.TryParse(ArtNr.Substring(ArtNrLenght - i), Tempnumber) Then
    15. i -= 1
    16. Exit For
    17. End If
    18. Next
    19. End If
    20. 'Wenn Number 0 bleibt ist das letzte Zeichen kein String
    21. If Number = 0 Then
    22. NewArtNr = ArtNr & 1
    23. Else
    24. NewArtNr = (ArtNr.Substring(0, i) & (Number + 1)).ToString
    25. End If
    26. 'Return NewArtNr funktioniert: Der Rest hier unten nicht. siehe unten
    27. 'Prüfen ob ArtNr bereits vergeben, wenn ja Funktion neu aufrufen
    28. If Not ArtNrExists(NewArtNr) Then
    29. Return NewArtNr
    30. Else
    31. increaseArtNR(NewArtNr)
    32. End If
    33. End Function

    Nachdem ich nun meine neue Artikelnummer habe, prüfe ich noch, ob diese bereits vergeben wurde.
    Also ich kopiere den Artikel mit der Nummer 1d23, aber es gibt schon einen Artikel mit Nummer 1d24, also soll weiter erhöht werden, bis die Artikelnummer nicht mehr vorkommt.
    Dafür habe ich folgenden Code:

    VB.NET-Quellcode

    1. Private Function ArtNrExists(ArtNr As String) As Boolean
    2. Dim articlerow = DtsArticles.Article
    3. If articlerow.Rows.Count < 1 Then Return False
    4. For Each row In articlerow
    5. If row.ArtNr = ArtNr Then
    6. Return True
    7. End If
    8. Next
    9. Return False
    10. End Function


    Und das funktioniert leider nicht.
    Wenn ich das ganze im Einzelschritt durchgehe (mit dem Beispiel 1d23 wird kopiert, 1d24 gibts schon, 1d25 soll rauskommen),
    funktioniert der Code soweit.
    Aus 1d23 wird 1d24, die Prüfung ob existiert gibt True zurück und increaseArtNr wird mit dem Parameter "1d24" neu aufgerufen.
    Dann wird aus 1d24, 1d25 und die Prüfung gibt False zurück.
    Die Funktion increaseArtNr springt dann auch an die richtige Stelle

    VB.NET-Quellcode

    1. If Not ArtNrExists(NewArtNr) Then
    2. Return NewArtNr

    und NewArtNr hat den Wert 1d25 (wie er auch sein soll). Danach hüpft er zu End Function. Aber statt die Function dann zu verlassen, hüpft er zurück zu: increaseArtNR(NewArtNr) und NewArtNr hat den Wert 1d24 und springt dann zu Exit Function.
    Die Funktion wird dann ohne Rückgabewert verlassen.

    Habe ich hier einen logischen Fehler, der mir entgangen ist?
    Wenn das anhand von "nur Code" too much ist, bastel ich natürlich gerne auch wieder eine Demo

    DerSmurf schrieb:

    Wie muss diese "isdbnull" Abfrage richtig aussehen?
    If Not selectedArticle.IsName1Null() Then. IsDbNull kommt aus dem zu entsorgenden Microsoft.VisualBasic-Namespace. Aber um die Frage zu beantworten: If Not Microsoft.VisualBasic.IsDbNull(selectedArticle.Name1) Then. Aber wie gesagt: nimm das andere genannte.

    Bzgl. der Function: siehe Anhang 1 und 2. Sobald alles scharfgestellt wurde, was VS nativ so hergibt, wird auch klar, dass der rekursive Aufruf von increaseArtNR() in Zeile#33 gar nix zurückgibt. Hätte da ein Return increaseArtNR() hingesollt?
    Bilder
    • ProjectProperties.png

      31,1 kB, 904×735, 56 mal angesehen
    • CompilerComplaining.png

      12,19 kB, 1.003×197, 54 mal angesehen
    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.

    DerSmurf schrieb:

    Wenn ein Wert, den ich in meiner List(Of Tuples) übergebe DNULL ist, schmiert das Programm ab
    Na, dann übergib ihn nicht.
    Ich frag mich eh, wie du solch einen Wert ühaupt abrufst. DbNull bedeutet: Der Wert ist nicht gesetzt, und kann daher auch nicht abgerufen werden.
    Sauber programmiert sind eiglich die IsDbNull()-Methoden vorgesehen, um abzuprüfen, ob ein Wert gesetzt ist.
    Und wenn nicht, darf man ihn nicht abrufen - im typDataset zB wird solch mit einer Exception quittiert.
    Ja, das ich so etwas abfangen muss, ist mir bewusst.
    Jedoch habe ich über google nur DBNull Abfragen aus dem alten Namespace gefunden.
    Der Vollständigkeit halber hier der Übergabecode, nach @VaporiZeds Hilfe:

    VB.NET-Quellcode

    1. ​Private Sub BTNCopyArticle_Click(sender As Object, e As EventArgs) Handles BTNCopyArticle.Click
    2. 'Daten des aktuell ausgewählten Artikels auslesen
    3. If ArticleBindingSource.Current Is Nothing Then Exit Sub
    4. Dim SelectedArticle = DirectCast(DirectCast(ArticleBindingSource.Current, DataRowView).Row, DtsArticles.ArticleRow)
    5. 'Artikelnummer um eins erhöhen
    6. Dim ArtNr As String = increaseArtNR(SelectedArticle.ArtNr)
    7. 'Daten des Artikels an bearbeitenForm übergeben
    8. Dim tpls As New List(Of Tuple(Of DataColumn, Object))
    9. With DtsArticles.Article
    10. 'Werte die belegt sein müssen übergeben
    11. tpls.Add(Tuple.Create(Of DataColumn, Object)(.ArtNrColumn, ArtNr))
    12. tpls.Add(Tuple.Create(Of DataColumn, Object)(.Name1Column, SelectedArticle.Name1))
    13. tpls.Add(Tuple.Create(Of DataColumn, Object)(.VeColumn, SelectedArticle.Ve))
    14. tpls.Add(Tuple.Create(Of DataColumn, Object)(.ListPriceColumn, SelectedArticle.ListPrice))
    15. tpls.Add(Tuple.Create(Of DataColumn, Object)(.DiscountColumn, SelectedArticle.Discount))
    16. tpls.Add(Tuple.Create(Of DataColumn, Object)(.PurchasingPriceColumn, SelectedArticle.PurchasingPrice))
    17. tpls.Add(Tuple.Create(Of DataColumn, Object)(.SalesMarginColumn, SelectedArticle.SalesMargin))
    18. tpls.Add(Tuple.Create(Of DataColumn, Object)(.RetailPriceColumn, SelectedArticle.RetailPrice))
    19. tpls.Add(Tuple.Create(Of DataColumn, Object)(.SupplierIDColumn, SelectedArticle.SupplierID))
    20. tpls.Add(Tuple.Create(Of DataColumn, Object)(.TaxColumn, SelectedArticle.Tax))
    21. 'Werte die belegt sein können, übergeben, wenn gefüllt
    22. If Not SelectedArticle.IsName2Null() Then
    23. tpls.Add(Tuple.Create(Of DataColumn, Object)(.Name2Column, SelectedArticle.Name2))
    24. End If
    25. If Not SelectedArticle.IsNoteNull() Then
    26. tpls.Add(Tuple.Create(Of DataColumn, Object)(.NoteColumn, SelectedArticle.Note))
    27. End If
    28. ArticleBindingSource.EditNew(Of frmEditArticle)(tpls)
    29. End With
    30. End Sub

    DerSmurf schrieb:


    VB.NET-Quellcode

    1. Dim tpls As New List(Of Tuple(Of DataColumn, Object))
    2. With DtsArticles.Article
    3. 'Werte die belegt sein müssen übergeben
    4. tpls.Add(Tuple.Create(Of DataColumn, Object)(.ArtNrColumn, ArtNr))
    5. tpls.Add(Tuple.Create(Of DataColumn, Object)(.Name1Column, SelectedArticle.Name1))
    6. tpls.Add(Tuple.Create(Of DataColumn, Object)(.VeColumn, SelectedArticle.Ve))
    7. tpls.Add(Tuple.Create(Of DataColumn, Object)(.ListPriceColumn, SelectedArticle.ListPrice))
    8. tpls.Add(Tuple.Create(Of DataColumn, Object)(.DiscountColumn, SelectedArticle.Discount))
    9. tpls.Add(Tuple.Create(Of DataColumn, Object)(.PurchasingPriceColumn, SelectedArticle.PurchasingPrice))
    10. tpls.Add(Tuple.Create(Of DataColumn, Object)(.SalesMarginColumn, SelectedArticle.SalesMargin))
    11. tpls.Add(Tuple.Create(Of DataColumn, Object)(.RetailPriceColumn, SelectedArticle.RetailPrice))
    12. tpls.Add(Tuple.Create(Of DataColumn, Object)(.SupplierIDColumn, SelectedArticle.SupplierID))
    13. tpls.Add(Tuple.Create(Of DataColumn, Object)(.TaxColumn, SelectedArticle.Tax))
    14. 'Werte die belegt sein können, übergeben, wenn gefüllt
    15. If Not SelectedArticle.IsName2Null() Then
    16. tpls.Add(Tuple.Create(Of DataColumn, Object)(.Name2Column, SelectedArticle.Name2))
    17. End If
    18. If Not SelectedArticle.IsNoteNull() Then
    19. tpls.Add(Tuple.Create(Of DataColumn, Object)(.NoteColumn, SelectedArticle.Note))
    20. End If
    21. ArticleBindingSource.EditNew(Of frmEditArticle)(tpls)
    22. End With
    Hihi - aber mit TupleList wärs schon schöner, odr? ;)

    Visual Basic-Quellcode

    1. With DtsArticles.Article
    2. 'Werte die belegt sein müssen übergeben
    3. Dim tpls = TupleList.From(.ArtNrColumn, CObj(ArtNr))(.Name1Column, SelectedArticle.Name1)(.VeColumn, SelectedArticle.Ve)
    4. (.ListPriceColumn, SelectedArticle.ListPrice)(.DiscountColumn, SelectedArticle.Discount)(.PurchasingPriceColumn, SelectedArticle.PurchasingPrice)
    5. (.SalesMarginColumn, SelectedArticle.SalesMargin)(.RetailPriceColumn, SelectedArticle.RetailPrice)
    6. (.SupplierIDColumn, SelectedArticle.SupplierID)(.TaxColumn, SelectedArticle.Tax))
    7. 'Werte die belegt sein können, übergeben, wenn gefüllt
    8. If Not SelectedArticle.IsName2Null() Then tpls.Add(.Name2Column, SelectedArticle.Name2)
    9. If Not SelectedArticle.IsNoteNull() Then tpls.Add(.NoteColumn, SelectedArticle.Note)
    10. ArticleBindingSource.EditNew(Of frmEditArticle)(tpls)
    11. End With

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

    @VB1963 Aber die Werte, um die es hier geht, sollen ja leer sein.
    "Name2" z.B. wird nur vergeben, wenn der Artikelname sehr lang ist, oder dort etwas rein kommt, was nicht wirklich zum Namen gehört.
    In den meisten Fällen bleibt dies aber einfach leer

    @ErfinderDesRades Ja, schöner ist dein Code schon, aber ist das einsparen von 11 Zeilen Code, wirklich den Import deiner kompletten Helpers wert?
    Zumal ich meinen Code tatsächlich (aus Anfängersicht) etwas übersichtlicher finde.