LINQ to Entities: Benutzerdefinierter Filter

  • VB.NET

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von Deep-Sea.

    LINQ to Entities: Benutzerdefinierter Filter

    Hallo allerseits,

    da dies mein erster Post in diesem Forum ist, mal ganz kurz etwas zu mir: Ich bin Chris, 26 und programmiere seit ca. 13 Jahren - erst als Hobby, dann beruflich. Angefangen und bis vor kurzem auch intensiv genutzt habe ich mit Delphi, später kam noch C dazu (ja C, nicht C++ oder C#). Durch einen neuen Job heißt es nun aber für mich seit einigen Monaten: VB.NET! ^^

    Zum eigentlichen Thema:
    Für ein neues Projekt habe ich zum ersten mal LINQ to Entities eingesetzt. Als Datenbank wird aktuell entweder SQLite oder MySQL verwendet.
    Nun wäre es aber sehr praktisch, wenn der Benutzer die Daten auch durchsuchen bzw. filtern könnte, die ich ihm im DataGridView präsentiere.
    Erste Idee war natürlich ein DataView, was ja aber leider nur mit DataTables arbeitet.
    Dann kam ich auf System.Linq.Dynamic. Das geht bei String-Feldern auch ganz gut, bei anderen Typen wird's aber etwas schwierig. Zumindest wenn die Suchfunktion dynamisch arbeiten soll und ich nicht jedes Feld manuell hinzufügen muss - was mir sehr lieb wäre.

    Ich denke nicht, dass ich der erste bin der den Benutzer etwas suchen lassen möchte. Was wäre denn der beste Weg, eine Suchfunktion zu implementieren? Sie muss (erstmal) nicht allzu komplexe Möglichkeiten bieten, dafür aber die möglichen Felder einfach und dynamisch laden können.


    An sich ist LINQ schon interessant und praktisch, aber manchmal ... :cursing:
    Hallo,

    Deep-Sea schrieb:

    Als Datenbank wird aktuell entweder SQLite oder MySQL verwendet.
    -->

    Deep-Sea schrieb:

    DataView, was ja aber leider nur mit DataTables arbeitet.
    Die DB liefert dir im Programm ein DataSet an, das durch einen DataAdapter gefüllt wurde. Aus diesem DataSet kannst du einzelne DataTables abrufen und in deinem DataGridView anzeigen. Dazwischen kannst du den von dir genannten Filter (DataView) setzen. Kurz gesagt: Ich verstehe nicht, was das Problem ist. Soll das Teil denn dynamisch konfigurierbar sein (etwa wie der AutoFilter in Excel)? Dafür brauchst du kein LINQ - alle Filterangaben kannst du in das DataView eintragen.

    Wenn das nicht geht kannst du Ausdrücke für dynamic LINQ generieren und damit manuell filtern; Beispiel:
    Tabelle:
    ID Name Frucht Anzahl
    1 Klaus Banane 22
    2 Susi Pflaume 15
    [...]

    Generiere für jede Spalte ein Menü / eine sinnvolle Auswahlmöglichkeit:
    ID >/>=/</<=/=/!= [Wert]
    Frucht = [Wert]
    [...]

    Wählt der Benutzer nun z.B. ID > 1 aus und gibt an, dass Frucht != Banane sein soll, generierst du folgenden dynamic-LINQ-Ausdruck:

    VB.NET-Quellcode

    1. Dim result = dataTable.Where("ID > 1 And Frucht <> Banane")
    Das Ergebnis zeigst du dann an. Den Filterausdruck kannst du wie oben gesagt auch in das DataView eintragen.

    In deinem Fall bietet sich auch WPF an - damit wird das dynamische Generieren der Auswahlmöglichkeiten ein Kinderspiel, denn das geht mit der richtigen Bindung vollautomatisch.
    Gruß
    hal2000

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

    hal2000 schrieb:

    Die DB liefert dir im Programm ein DataSet an [...]

    Ich nutze aber das Entity Framework. Dort werden mir die Tabellen erst einmal nur als ObjectSet angeboten.
    Wenn man die Daten aber dort trotzdem irgendwie als DataSet bekommen kann, wäre ich für den Hinweis schon mal sehr dankbar.

    Aber auch dann geht es ja weiter, denn ich will nicht bloß eine einfache Tabelle darstellen, sondern eine etwas komplexere Abfrage die u.a. Fremdschlüssel auflöst. Das hatten ich im Eingangsposting wohl vergessen zu erwähnen. Diese Abfrage bringt mir dann ja ein IQueryable(Of <anonymer Typ>) zurück.


    hal2000 schrieb:

    Wenn das nicht geht kannst du Ausdrücke für dynamic LINQ generieren und damit manuell filtern [...]

    Mir ist schon klar, wie ich grundsätzlich mit Dynamic-LINQ filtern kann. Das Problem sind verschiedene Datentypen.
    Ideal wäre für einen String das:

    VB.NET-Quellcode

    1. Query.Where("Beschreibung.Contains(@0)", VariableBenutzereingabe)

    Klappt auch super, aber nicht für Integer, Date, Nullables, etc.
    Ich würde gerne erst einmal alle Felder als String durchsuchen. Versuche ich aber z.B. bei einem Date innerhalb der Dynamic-LINQ-Abfrage noch ein ToString zu machen, löst das den Fehler aus, dass es diese Funktion nicht gibt.
    Wenn, dass muss ich schauen welchen Datentyp die Spalte hat, in der gesucht werden soll.
    Klar, das ist an sich möglich, aber dann müsste ich ja für jeden Datentyp eine eigene Behandlungsroutine schreiben.
    Ich kann irgendwie nicht glauben, dass das so kompliziert sein soll für eine lausige Suche.

    Wieso kann man das Query nicht in ein DataSet wandeln, damit das mit DataView klappt?

    Deep-Sea schrieb:

    Ich kann irgendwie nicht glauben, dass das so kompliziert sein soll für eine lausige Suche.

    In anderen Sprachen hängen die Operationen genauso davon ab. So kannst Du beispielsweise in SQL die Operatoren >, < nur für zahlen anwenden, LIKE funktioniert bei Strings, etc.
    Darf ich erfahren, was Du denn erwartet hast? Wie soll es sonst funktionieren?
    Also LIKE funktioniert zumindest bei SQLite und MySQL auch mit Zahlen und Datumsangaben.
    Und ich schätze mal, dass auch der Filter von DataView alles als String betrachtet. So kenne ich es zumindest von Delphi.
    Und mehr will ich auch gar nicht. Wenn der Benutzer "2013" angibt, soll es egal sein ob er in einem Datumsfeld, einem Mengenfeld oder einer Bezeichnung sucht.
    also zunächstmal: EntityFramework ist eine ganz annere Technologie als Dataset, aber beide beackern prinzipiell dasselbe Anforderungs-Gebiet. Keine gute Idee ists, die EF-Objekte etwa in ein Dataset umzufüllen, um Dataset-Techniken anwenden zu können - EF hat seine eigenen Techniken - ich kenne sie nicht gut, aber sind um ca. 6 jahre weiter entwickelt, also das wird schon was taugen.

    Was wäre denn der beste Weg, eine Suchfunktion zu implementieren?
    Geht sowas nicht schon?

    VB.NET-Quellcode

    1. grid.DataSource= From bla in myObjectContext.Table1 where bla.DecimalValue > numericUpdown1.Value
    Das wäre etwa ein Filter für Zahlenwerte (typ Decimal)

    ErfinderDesRades schrieb:

    Geht sowas nicht schon?

    VB.NET-Quellcode

    1. grid.DataSource= From bla in myObjectContext.Table1 where bla.DecimalValue > numericUpdown1.Value
    Das wäre etwa ein Filter für Zahlenwerte (typ Decimal)
    Natürlich geht so etwas in der Art. Aber mit statischem LINQ müsste ich für jede Spalte in jeder Tabelle die der Benutzer durchsuchen können soll eine eigene Behandlungsroutine schreiben.

    Ich habe mal etwas mit einer DataTable getestet. Es ist eigentlich genau das, was ich suche.

    VB.NET-Quellcode

    1. BindingSource1.Filter = String.Format("CONVERT(spalte, 'System.String') LIKE '%{0}%'", TextBox1.Text)

    :wacko:
    tja, ich habe die untypisierte Art, wie DataTable filtert oder sortiert, immer für ein Manko gehalten.
    Ich denke, ist auch sehr selten, dass ganz undifferenziert in allen Spalten nach einem String gesucht werden soll.
    Aber wenn du deinen Laden umstimmen kannst, auf Dataset umzusteigen - ich fänds gut, ich bin mit EF immer an ganz annere Beschränkungen gestoßen, die mir den Spaß dran verdarben.
    Also wennde Lust hast auf Grundsatz artikel zu databinding-getriebene Anwendungen: vier Views
    Mit Dataset geht das wunderbar umzusetzen, mit EF stößt man hier und da auf Grenzen.