Nur Artikel aus gefilterter Bindingsource durchsuchen, statt der ganzen DataTable

  • VB.NET

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von DerSmurf.

    Nur Artikel aus gefilterter Bindingsource durchsuchen, statt der ganzen DataTable

    Nabend ihr lieben
    Ich habe eine Klasse erstellt, welche ich an verschiedenen Stellen in meinem Programm verwende, um einen Artikel nach Eingabe eines EAN Code zu finden.
    Ich durchsuche bisher die komplette Artikel Datatable (mittels FirstOrDefault), nach vorkommen des EAN Codes und gebe dann den gefundenen Artikel an die aufrufende Sub zurück.
    Nun habe ich aber mehrere Stelle in meinem Programm, wo diese Artikelliste gefiltert sein kann (mittels BS.Filter).
    Da meine EANSuchKlasse, aber die gesamte DataTable durchsucht finde ich unter Umständen Artikel, welche in der Filterung garnicht vorkommen.
    Ist es möglich folgende Sub so umzuarbeiten, dass eben nicht die DataTable, sondern die BS (welche ich dann übergeben würde) durchsucht wird?

    VB.NET-Quellcode

    1. Private Function SearchItemByEAN(EANCode As String) As (ItemFound As Boolean, Itemrow As DtsDaten.ArtikelRow)
    2. If _Dts.Artikel.Count < 1 Then Return (False, Nothing)
    3. Dim Founditem As DtsDaten.ArtikelRow
    4. If _FilterByCompanies Then
    5. Founditem = _Dts.Artikel.FirstOrDefault(Function(z) _ListofCompaniesToOrder.Select(Function(x) x.ID).Contains(z.LieferantID) AndAlso z.EAN = EANCode)
    6. Else
    7. Founditem = _Dts.Artikel.FirstOrDefault(Function(z) z.EAN = EANCode)
    8. End If
    9. If Founditem Is Nothing Then
    10. Return (False, Nothing)
    11. Else
    12. Return (True, Founditem)
    13. End If
    14. End Function

    *Topic verschoben*

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Marcus Gräfe“ ()

    Ja, warum nicht? Die BS hat ja eine List-Property. Ist dann allerdings untypisiert. Daher hab ich in einer meiner DLLs ne Extension im Sortiment:

    VB.NET-Quellcode

    1. <Extension> Public Function List(Of T)(Bs As BindingSource) As List(Of T)
    2. If Bs.Position < 0 Then Return New List(Of T)
    3. Return Bs.List.Cast(Of T).ToList
    4. End Function


    Ach, Moment. Filter … hm, kann ich gar nicht momentan prüfen, weil ich den nie verwende. Ich filtere ja anders. Ach doch, scheint zu passen.

    btw: Wieviele Artikel hast Du denn mit gleicher EAN? Wenn die Antowrt lautet: »Maximal einen, niemals mehrere, das wäre dann ein Datensatzfehler.«, dann verwende statt FirstOrDefault besser SingleOrDefault.
    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“ ()

    Ich verwende für sowas dieses hier:

    VB.NET-Quellcode

    1. <Extension()>
    2. Public Function All(Of T As DataRow)(subj As BindingSource, Optional filter As Func(Of T, Boolean) = Nothing) As IEnumerable(Of T)
    3. If filter Is Nothing Then Return From drv In subj.Cast(Of DataRowView)() Select DirectCast(drv.Row, T)
    4. Return From drv In subj.Cast(Of DataRowView)() Where filter(DirectCast(drv.Row, T)) Select DirectCast(drv.Row, T)
    5. End Function
    6. 'Aufruf
    7. Dim rels = bsRelation.All(Of RelationRow).ToList 'ergibt diejenigen RelationRows, die über bsRelation angezeigt werden - in Reihenfolge und Filterung der Bs
    8. 'oder so
    9. Dim rels = bsRelation.All(Of RelationRow)(Function(x) x.Name = "huhu").ToList 'filtert von obigen zusätzlich diejenigen mit .Name="huhu"

    VaporiZed schrieb:

    Wieviele Artikel hast Du denn mit gleicher EAN?

    Jeder EAN Code kommt exakt einmal vor. Es ist auch sichergestellt, dass der User keinen EAN doppelt vergeben kann. Trotzdem steht in der Dt.EAN Spalte Unique auf false, denn ein EAN kann leer sein.
    Hier steht allerdings DT.EAN.AllowDBNull auch auf false und der default Value auf einen Leerstring. Also gibt es schon jeden EAN nur einmal, es sei denn es gibt keinen EAN Code.
    Aber ich verstehe den Unterscheid zwischen Single und First auch nicht.
    First liefert mir das erste, Single liefert mir das Einzige Element zurück. (bzw. in beiden Fällen nothing, wenn ichs default mit verwende).
    Also doch in meinem Fall exakt das gleiche, weil das erste ohnehin das einzige Elemt ist?

    Und sorry, ich stehe mal wieder auf dem Schlauch. Habe die Extension in meine Extensions gepackt und erzeuge nun mittels BSArtikel.List eine IList welche alle Artikelrows der BS enthält (hoffe das stimmt soweit)?
    Aber mit dieser Liste stehen mir säntliche Linq Ausdrücke nicht zur Verfügung.

    VB.NET-Quellcode

    1. Private Sub StartEANSEarch()
    2. Dim test = BSArtikel.List.Firstordefault(Function(z) z.EAN = EANCode)
    3. End Sub

    Was verraffe ich hier?
    Ich hatte zunächst die Extension von @VaporiZed verwendet.

    Mit deiner Extension @ErfinderDesRades klappts.
    Hier mein banaler Test:

    VB.NET-Quellcode

    1. Private Sub StartEANSEarch()
    2. Dim test = BSArtikel.All(Of ArtikelRow)
    3. Dim xx = test.FirstOrDefault(Function(z) z.EAN = _EANCode)
    4. If Not xx Is Nothing Then
    5. MessageBox.Show(xx.Name1)
    6. Else
    7. MessageBox.Show("nix gefunden")
    8. End If
    9. End sub


    Das werde ich jetzt mal in meine EAN Klasse einbauen.

    Edit: ne, wadde mal. Mit oben geposteten Code finde ich Artikel nur, wenn die Bindingsource nicht gefiltert ist.
    Also muss ich ja scheinbar meinen BSFilter der extension mitgeben. Das wird tricky, denn mein Filter ist ein bisschen tricky.

    Ich sehe aber gerade in meinem Post oben fehlt das .ToList.
    Wenn ichs also richtig mache und ​Dim test = BSArtikel.All(Of ArtikelRow).ToList verwende, wird wiederum kein Artikel gefunden.

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

    DerSmurf schrieb:

    ne, wadde mal. Mit oben geposteten Code finde ich Artikel nur, wenn die Bindingsource nicht gefiltert ist.
    na dann ist _EANCode nicht in der BS, wenn ihr Filter an ist.



    DerSmurf schrieb:

    Also muss ich ja scheinbar meinen BSFilter der extension mitgeben.[...]tricky.
    Nein - keinesfalls den bs-Filter mitgeben.

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

    DerSmurf schrieb:

    Ich hatte zunächst die Extension von @VaporiZed verwendet.
    Hmnee. Bei meiner Extension muss auch eine Typangabe gemacht werden, also BSArtikel.List(Of DeineDataRow). Sonst landest Du bei der untypisierten BS-List-Property - wie ich geschrieben hatte.

    DerSmurf schrieb:

    Aber ich verstehe den Unterscheid zwischen Single und First auch nicht.
    First liefert mir das erste, Single liefert mir das Einzige Element zurück. (bzw. in beiden Fällen nothing, wenn ichs default mit verwende).
    Also doch in meinem Fall exakt das gleiche, weil das erste ohnehin das einzige Elemt ist?
    Es verhindert aber (vor allem, wenn Du Unique auf False stellst), dass Du 2 Items mit einer EAN hinterlegen kannst. Wenn Du 2 Artikel mit gleicher EAN hast und FirstOrDefault aufrufst, bekommst Du den ersten Artikel. Bei SingleOrDefault bekommst Du eine Exception - bei der Du dann weißt: oh, da hat sich ein Datensatzfehler eingeschlichen!
    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 3 mal editiert, zuletzt von „VaporiZed“ ()

    Soho.
    Es funktioniert alles. Ich habe meinen alten EANSuchen Code komplett auskommentiert. Unter anderem auch die Rücksetzung der ​_EANCode as string Variable nach einer Suche.
    Habe das ganze aber nun in meiner EANSuchklasse. Hier gibt es zwei Public Sub New, einer wird eine DataTable übergeben, der anderen eine Bindingsource. Entsprechend wird dann durchsucht.

    Dann werde ich die Suche auf SingleOrDefault umstellen. Hier muss ich aber noch ein bisschen rumtesten, dass ich alle Fehler abfange, damit der User nicht mit kryptischen Fehlermeldung belastet wird.

    ErfinderDesRades schrieb:

    mir scheint, die Vorzüge von Extension-Methods sind bei dir noch nicht angekommen.

    @VaporiZed hat sich viel Mühe gegeben mir das einzutrichtern.
    Aber es reicht in meinem aktuellen Programm nur für absolute basics, zum schauen ob da nur Zahlen in nem String sind, ob der String leer ist, und sowas.

    Aber! Du musst mir zugute halten, dass es immerhin schonmal eine Klasse ist (und alle Forms eben diese Klasse nutzen), statt den immer gleichen Code auf jeder Form.
    Eure Geduld mit mir zahlt sich stückchenweise aus :o)