Autor Beitrag
JohnDyr
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 56
Erhaltene Danke: 1

Win 10
C# (VS 2017)
BeitragVerfasst: Sa 05.01.19 14:41 
Liebe Community,

ich stehe mal wieder auf dem Schlauch. Der Code sagt glaube ich alles...

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
            switch (module)
            {
                case EModule.Carrier:
                    SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM [View1]", Connection);
                    da.Fill(res);
                    break;
                case EModule.Customer:
                    // wie kann ich das besser umsetzen? Ich möchte nicht jedesmal ein SqlDataAdapter Objekt erstellen :(
                    SqlDataAdapter da1 = new SqlDataAdapter("SELECT * FROM [View2]", Connection);
                    da1.Fill(res);
                    break;
                case EModule.Loader:
                    break;
                case EModule.Deloader:
                    break;
                default:
                    break;
            }
            return res;



Moderiert von user profile iconTh69: Topic aus WinForms verschoben am Sa 05.01.2019 um 14:32
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Sa 05.01.19 14:58 
Und warum willst du keinen neuen SqlDataAdapter erzeugen?
JohnDyr Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 56
Erhaltene Danke: 1

Win 10
C# (VS 2017)
BeitragVerfasst: Sa 05.01.19 15:13 
Naja, wenn man es sich ersparen kann, würde ich es mir gerne ersparen. Ich möchte das Programm so leichtgewichtig wie möglich programmieren. Mittlerweile habe ich folgendes vergeblich probiert...

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
            
DataTable res = new DataTable();

SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM '@table' ORDER BY [Zuletzt geändert] DESC", Connection);
da.SelectCommand.Parameters.AddWithValue("table", module.ToString());
da.Fill(res);

return res;


Funktioniert aber nicht...
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Sa 05.01.19 15:30 
Parameter machen keine Textersetzung. Parameter sind nur zum austauschen von Werten gedacht, also nicht für Tabellen oder Spaltennamen.
Gerade darum sind die auch so sicher. Niemand kann das eigentliche Verhalten des SQL von außen ändern da nur Werte ausgetauscht werden können und man das Verhalten durch einfügen ~cleverer~ Werte nicht ändern kann.

Zitat:
Naja, wenn man es sich ersparen kann, würde ich es mir gerne ersparen.


Was willst du dir da sparen :gruebel: Neue Objekte erzeugen ist in einem OO System so ziemlich der natürlichst vorstellbare Vorgang. Gerade so ein Adapter ist eine ziemlich leere Hülle. Da hängt am Konstructor kein großes Preisschild dran.

Als Best Practice bei ADO.Net (das ist hier kein Winforms Problem vielleicht kann da mal einer verschieben) gilt eh die entsprechend nötigen Instanzen immer so spät wie möglich zu erzeugen und so früh wie möglich zu zerstören (Usings sind da extrem hilfreich). Das betrifft insbesondere die Connection. Und da alle anderen relevanten Klassen (Commands, Adapter etc.) von der Connection abhängen betrifft es die mit.

Für diesen Beitrag haben gedankt: JohnDyr
JohnDyr Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 56
Erhaltene Danke: 1

Win 10
C# (VS 2017)
BeitragVerfasst: Sa 05.01.19 15:35 
Ja, habe eben weiter recherchiert und was ich möchte, kann man so nicht umsetzen. Dafür müsste ich Stored Procedures einsetzen. Meine Motivation ist halt, dass ich 4 Tabellen habe, welche von der Struktur her (fast) gleich sind. Jetzt den Datenbank Getter/Setter/Reader Code dafür 4 mal zu schreiben, finde ich uncool.

Zur vollständigkeithalber...

www.sommarskog.se/dynamic_sql.html
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Sa 05.01.19 15:49 
Das kannst du schon, nur mußt du dann den SQL-String per + zusammenbauen:
ausblenden C#-Quelltext
1:
string sql = "SELECT * FROM " + module + "...";					

Für diesen Beitrag haben gedankt: JohnDyr
JohnDyr Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 56
Erhaltene Danke: 1

Win 10
C# (VS 2017)
BeitragVerfasst: Sa 05.01.19 16:07 
user profile iconTh69 hat folgendes geschrieben Zum zitierten Posting springen:
Das kannst du schon, nur mußt du dann den SQL-String per + zusammenbauen:
ausblenden C#-Quelltext
1:
string sql = "SELECT * FROM " + module + "...";					


Genau DAS habe ich grade auch umgesetzt und es funktioniert. Ich frage mich ob diese Problemlösung "normal" ist. Ich kann ja nicht der erste sein, der dieses Problem hat.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Sa 05.01.19 16:26 
Zitat:
Ich frage mich ob diese Problemlösung "normal" ist.


Üblich und normal ja. Ob das gut ist ist eine andere Frage ;)

Zitat:
Jetzt den Datenbank Getter/Setter/Reader Code dafür 4 mal zu schreiben, finde ich uncool.


Der Code sollte doch identisch sein nur das SQL ändert sich. Wo ist das Problem das nötige SQL Statement zu erzeugen und dann an einen einheitlichen Code zu geben?
JohnDyr Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 56
Erhaltene Danke: 1

Win 10
C# (VS 2017)
BeitragVerfasst: Sa 05.01.19 16:52 
Zitat:
Üblich und normal ja. Ob das gut ist ist eine andere Frage ;)


Nicht gut, wegen SQL Injection Gefahr - verstehe ich.

Zitat:
Der Code sollte doch identisch sein nur das SQL ändert sich. Wo ist das Problem das nötige SQL Statement zu erzeugen und dann an einen einheitlichen Code zu geben?

Es gibt kein Problem. Funktionieren tut das auch. Ich finde es aus Sicht der Erweiterbarkeit und Wartbarkeit nur nicht so schön, wenn man fast den gleichen Code 4 mal hat (und das jeweils ca. 500 Zeilen).
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Sa 05.01.19 19:57 
Zitat:
Ich finde es aus Sicht der Erweiterbarkeit und Wartbarkeit nur nicht so schön, wenn man fast den gleichen Code 4 mal hat (und das jeweils ca. 500 Zeilen).


Welchen Code brauch man da 4 mal?

Ein Beispiel
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
public DataTable GetDataforModule(EModule module)
{
    switch (module)
    {
        case EModule.Carrier:
            return GetData("SELECT col1, col2, col3 FROM [View1]", meinLieberConnectionString);
        case EModule.Customer:
            return GetData("SELECT col4, col5, col6 FROM [View2]", meinLieberConnectionString);
        // etc.
    }
}

public DataTable GetData(string sql, string conn)
{
    DataTable dataTable = new DataTable();
    using (var con = new SqlConnection(conn))
    {
        con.Open();
        using (var adapter = new SqlDataAdapter(sql, con))
        {
            adapter.Fill(dataTable);
        }
    }
    return dataTable;
}
JohnDyr Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 56
Erhaltene Danke: 1

Win 10
C# (VS 2017)
BeitragVerfasst: So 06.01.19 13:30 
Zitat:
Welchen Code brauch man da 4 mal?


Ich habe noch diverse SQL "Getter" Methoden welche in etwa so aussehen:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
GetNameById(id)
SELECT name FROM table1 WHERE id = @id

GetNameById(id)
SELECT name FROM table2 WHERE id = @id

GetNameById(id)
SELECT name FROM table3 WHERE id = @id


und das gleiche jetzt nicht nur für Name sondern auch weitere Informationen (Adresse, Land) usw. Der Aufbau dieser Tabellen ist identisch (Spalten sind gleich). Die Source ist halt immer eine andere.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: So 06.01.19 15:40 
Eine Methode zu schreiben der man den Tabellennamen übergibt um das passende SQL zu basteln scheint dann aber jetzt auch nicht so aufwendig.

Das eigentliche Grundübel scheint dann wohl eher ein kaputtes Datenbankmodel zu sein. Mehrere Tabellen/Views mit identischen Aufbau zu haben hat ein Geschmäckle.
JohnDyr Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 56
Erhaltene Danke: 1

Win 10
C# (VS 2017)
BeitragVerfasst: So 06.01.19 16:38 
user profile iconRalf Jansen hat folgendes geschrieben Zum zitierten Posting springen:
Eine Methode zu schreiben der man den Tabellennamen übergibt um das passende SQL zu basteln scheint dann aber jetzt auch nicht so aufwendig.

Das eigentliche Grundübel scheint dann wohl eher ein kaputtes Datenbankmodel zu sein. Mehrere Tabellen/Views mit identischen Aufbau zu haben hat ein Geschmäckle.


Ich zügel mich davor zu sagen, dass mein Datenmodell optimal ist... aber was besseres ist mir nicht eingefallen. Irgendwo ist es ja auch Geschmackssache. Kurze Erläuterung: Angenommen du hast zwei Stammdatensätze: Absender und Empfänger

Beide haben gleiche Attribute wie: Vorname, Nachname, Straße, Hausnummer, PLZ, Ort, Land

Würdest du jetzt zwei Tabellen erstellen mit den gleichen Attributen oder eine Tabelle und darin eine weitere Spalte mit "Typ"? Oder gibt es noch eine dritte Möglichkeit? Wie würde man denn sowas am besten abbilden..? :?:


Zitat:
Eine Methode zu schreiben der man den Tabellennamen übergibt um das passende SQL zu basteln scheint dann aber jetzt auch nicht so aufwendig.

Nein ist es nicht, habe deshalb diese Lösung umgesetzt.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: So 06.01.19 20:08 
Zitat:
Würdest du jetzt zwei Tabellen erstellen mit den gleichen Attributen oder eine Tabelle und darin eine weitere Spalte mit "Typ"? Oder gibt es noch eine dritte Möglichkeit? Wie würde man denn sowas am besten abbilden..? :?:


Das ist allgemein schwer zu sagen. Bei einem Absender/Empfänger System kann es hilfreich sein da 2 Tabellen zu nehmen muss aber nicht.

So ohne Kontext würde ich eher zu einer Tabelle tendieren. Absender/Empfänger klingt eher nach einer Beziehung zu etwas. Also nicht zwei Tabellen und auch kein Typ in der einen Tabelle. Man ist Empfänger/Absender von etwas und dieses etwas ist eine Tabelle (z.B. Mail/Brief/Paket/Nachricht etc.) und diese Tabelle hat zwei Beziehungen zu einer Personen/Kunden/Benutzer etc. Tabelle. Die Beziehung zwischen Ding und Person ist also Absender oder Empfänger.

Oder in dem Fall das es z.b. mehrere Empfänger oder andere Rollen neben Absender und Empfänger geben könnte (Überbringer oder sowas) dann könnte es eine Mapping Tabelle zwischen Ding und Person geben kann an der dann ein entsprechender Typ hängt.