Laden...

Aufbaue einer Datenbankabfrage mit variablen Filtern

Erstellt von Kriz vor 3 Jahren Letzter Beitrag vor 3 Jahren 512 Views
K
Kriz Themenstarter:in
141 Beiträge seit 2017
vor 3 Jahren
Aufbaue einer Datenbankabfrage mit variablen Filtern

Verwendetes Datenbanksystem: <SQL>

Hallo zusammen, folgende Situation:
Es sollen Abfragen an eine Web-Rest-API gesendet werden, mit verschiedenen möglichen Filtern. Die Filter können sehr variable gestaltet sein, es können drei int - Arrays mit je sechs Werten sein, oder aber auch nur ein string-Wert.
Die API wurde in C# entwickelt, steht schon in den Grundzügen und greift auf eine MSQL Datenbank zu.
Gibt es eine Möglichkeit eine SQL Abfrage so dynamisch zu gestalten, dass jeder mögliche "Filter-Fall" abgedeckt wird, oder muss ich die Abfragen mittels if-then händisch als SELECT Statement schreiben?
Aktuelle gibt es folgende Filter, die können aber jederzeit variieren:
string Wert1 (kann auch null sein)
int[] Wert2 (0 - 30) (kann auch null sein)
int[] Wert3 (0 - 30) (kann auch null sein)
int[] Wert4 (0 - 30) (kann auch null sein)

Ich hoffe ich konnte mich verständlich ausdrücken
Danke schonmal!

Kriz

6.912 Beiträge seit 2009
vor 3 Jahren

Hallo Kriz,

greifst du mit dem SqlClient auf die DB zu od. wird ein O/R-Mapper ala EF Core, etc. verwendet?

Beim SqlClient kann das Statement (der SQL-String) manuell zusammengestöpselt werden. Achte dabei aber auf [Artikelserie] SQL: Parameter von Befehlen (das hat auch den Vorteil dass im SQL Server der Query-Plan gecached werden kann und so eine bessere Leistung vorhanden ist).

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

K
Kriz Themenstarter:in
141 Beiträge seit 2017
vor 3 Jahren

Hallo Gü,

ich greife direkt auf die DB mittels SQLClient zu.

Also wäre die beste Möglichkeit dann anhand der gesendeten Filter das Statement "händisch" zu erstellen und auszuführen?

6.912 Beiträge seit 2009
vor 3 Jahren

Hallo Kriz,

genau.

Statt simplen String-Verkettungen würde ich aber einen QueryStringBuilder erstellen.
Zuerst die einzelnen Filter in einer Liste speichern und dann daraus am Ende das SQL Statement erzeugt, da so auch einfach parametrisierbar ist.
So kannst du problemen mit den and-"Verknüpfungen" von vornhinein aus dem Weg gehen.

Klar?

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

K
Kriz Themenstarter:in
141 Beiträge seit 2017
vor 3 Jahren

Top, danke Dir!

3.825 Beiträge seit 2006
vor 3 Jahren

Ich habe bei allen Abfragen immer variable Filter.

Das sieht bei mir so aus :



// Alt
string sqlstr = "SELECT * FROM ad WHERE ";
if (such_ad_match.Text.Trim() != "") sqlstr += "ad_match LIKE '" + such_ad_match.Text.ToSqlString() + "%' AND ";
if (such_ad_nr.Text.Trim() != "") sqlstr += "ad_nr = '" + such_ad_nr.Text.ToSqlString() + "' AND ";
if (such_ad_kdnr.Text.Trim() != "") sqlstr += "ad_kdnr = '" + such_ad_kdnr.Text.ToSqlString() + "' AND ";
if (such_ad_nam1.Text.Trim() != "") sqlstr += "ad_name1 = '" + such_ad_name1.Text.ToSqlString() + "' AND ";
...

// Neu mit (eigenem) ORM und Parametern
clsDataQuery qry = new clsDataQuery("sn").Where();
if (such_sn_nr.Text != "")		qry = qry.sn_nr().IsLike(SuchfeldString(such_sn_nr)).And();
if (such_sn_arnr.Text != "")	qry = qry.sn_arnr().IsLike(SuchfeldStringExakt(such_sn_arnr)).And();
if (such_sn_status.Text != "")	qry = qry.sn_status().IsLike(SuchfeldStringExakt(such_sn_status)).And();
...

Der Code wird maschinell erstellt für Winforms, WPF und Xamarin.Forms.

Ich finde das für den Anwender sehr komfortabel. Für den Programmierer auch.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

16.864 Beiträge seit 2008
vor 3 Jahren

Sowas gibts schon fertig und auch SQL Injection Proof.
https://github.com/sqlkata/querybuilder

Gibt es eine Möglichkeit eine SQL Abfrage so dynamisch zu gestalten, dass jeder mögliche "Filter-Fall" abgedeckt wird, oder muss ich die Abfragen mittels if-then händisch als SELECT Statement schreiben?

Sowas steht im Endeffekt im Widerspruch: starre struktur und extrem dynamisch ist halt eher Wunschkonzert.

Das Problem ist:
API Modelle sind auch nur eine UI-Darstellung und haben i.d.R. eine andere Struktur als die Datenbank.
1:1 filtern, wie es zB. mit OData passiert, ist eher realitätsfern - hab ich persönlich noch nie funktionsfähig in der realen Welt gesehen; nur in Demos und in Lektüren.

Meistens hat man daher einen Parser für das REST-basierte Filterung für die Datenbank, da man eben 1:1 nicht die Filter weiter reichen kann.
Letzten Endes ist das aber eine individuelle Logik-Implementierung Deiner Anwendung; jede API ist da eben ein bisschen anders.

3.825 Beiträge seit 2006
vor 3 Jahren

Der Query Builder ist ja fast genauso wie mein ORM.

Ich habe es nach einem Vortrag der .NET User Group in Bad Homburg über Statemachines und Fluent APIs im Jahr 2015 geschrieben.

Ich kann diese Vorgehensweise sehr empfehlen weil die Programmierung wirklich sehr einfach und typsicher ist.

Eine Grammatik kann ich bei mir nicht einbauen da ich sonst keine fallweise Verknüpfungen machen kann wie


if (...) qry = qry.sn_nr().IsLike(SuchfeldString(such_sn_nr)).And();

Bzw. ich hab's nicht hinbekommen.

Zusätzlich erstelle ich für die Datenbankstruktur Klassen, so dass die Query typsicher ist und Intellisense funktioniert. Das macht der Query Builder nicht glaube ich.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3