Autor Beitrag
MagratKnoblauch
Hält's aus hier
Beiträge: 2



BeitragVerfasst: Sa 09.01.16 10:10 
Hallo Leute,
ich versteh einfach nicht was ich machen soll. Ich hab für mein kleines Ticketsystem-Programm versucht alle Datenbankzugriffe in eine eigene Klasse umzulagern. Jedoch versteh ich nicht was ich mit der Connection machen muss, damit die mir keine Fehler ausgibt
Wenn mir jemand helfen könnte wäre das echt toll. Schon mal danke(allein für's lesen).

pp. Sorry wenn das etwas stümperhaft geposted ist.

ausblenden volle Höhe 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:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
namespace Projekt2
{
    class Datenbank
    {
        OleDbConnection con = new OleDbConnection();
        OleDbCommand cmd = null;
        DataSet ds = new DataSet();
        OleDbDataAdapter adapter = null;
        OleDbDataReader dr = null;
        

        public OleDbConnection connection()
        {
            try
            {
                con.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=datenbank2.accdb";
            }

            catch (Exception a)
            {
                MessageBox.Show("Verbindungsfehler zur DB" + a);
            }

            if (con.State != ConnectionState.Open)
            {
                con.Open();
            }

            else
            {
                con.Close();
                con.Open();
            }
              
            return con;
        }


        public DataSet dataset(string sql)
        {
          connection();

            try
            {
                adapter = new OleDbDataAdapter(sql, con);

                ds.Clear();

                adapter.Fill(ds, "inhalt");
            }
            catch (Exception a)
            {
                MessageBox.Show("Fehler im Dataset" + a);
            }

            return ds;
        }


        public OleDbDataReader datareader(string sql)
        {
            connection();

            try
            {
                cmd = new OleDbCommand(sql, con);
                dr = cmd.ExecuteReader();               
            }
           catch (Exception a)
            {
                MessageBox.Show("Fehler im Datareader" + a);
            }

            return dr;
        }

        public void sqlausführen(string sql)
        {
            connection();

            try
            {
                cmd = new OleDbCommand(sql, con);
                cmd.ExecuteNonQuery();
            }
            catch (Exception a)
            {
                MessageBox.Show(" Fehler Sqlausführen" + a);
            }  
        }
    }
}


Moderiert von user profile iconTh69: Quote- durch C#-Tags ersetzt
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 09.01.16 11:46 
Zitat:
Ich hab für mein kleines Ticketsystem-Programm versucht alle Datenbankzugriffe in eine eigene Klasse umzulagern


Um was zu erreichen? Du solltest dich kurz selbst fragen warum du das tust ;)

Ich frage das so provokativ weil der Stil der Klasse inherent problematisch ist. Ich vermute mal das du irgendwie die Handhabung vereinfachen willst. Vereinfachen wird aber dann problematisch wenn man versucht weiter zu vereinfachen als hilfreich. Weil man mehr neue versteckte Problem einbaut als vorher überhaupt da waren.

Ein Beispiel. Du versuchst die Connection so zu kapseln so das sie von außen nicht direkt manipulierbar ist so das ich ein Aufrufer (theoretisch) nicht darum kümmern muss.
Deine Methoden veröffentlichen aber Klassen die ihrerseits die Connection weiterhin brauchen obwohl du sie aus der Reichweite des Users entfernt hast. Ohne die Klasse müßte man das explizit machen, man sieht das zum Beispiel eine Connection und ein DataReader zusammenhängen. Diesen Zusammenhang hast du versteckt (ein Benutzer deiner Klasse sieht das nicht) obwohl man immer noch direkt Wissen muss das es denn gibt damit man nix falsch macht.

Stell dir vor du möchtest mit deiner Klasse ein Massenkopieren (mit kleineren Manipulationen an den Daten) implementieren. Dazu würdest du über dataReader() einen DataReader ranholen und über die Zeilen des DataReaders iterieren. In der Schleife würdest du irgendwas mit der Datenzeile machen und dann in die Datenbank schreiben mit deiner sqlausführen Methode. Das würde nicht funktionieren wenn du das versuchst. sqlausführen würde die Connection schließen wieder öffnen und damit wäre der datareader kaputt der die Connection noch brauchte. Diesen Zusammenhang hast du effektiv versteckt was nicht gut ist. Ein explizites ausprogrammieren sähe aufwendiger aus den Zusammenhang würde man aber sofort erkennen.

Ich würde dir empfehlen die Klasse so zu schreiben das jede aufrufbare Methode die eine Connection braucht die Connection in einer Weise benutzt das sie nach Aufruf der Methode nicht mehr nötig ist und am Ende der jeweiligen Methode auch explizit geschlossen wird. Dann hast du die meisten Lücken geschlossen da du keine irgendwie herumfliegende Connection haben wirst.

Da ich die dataset Methode sinnfrei halte da da immer nur eine DataTable namens Inhalt drin ist und du immer wieder die gleiche DataSet Instanz wiederverwendest mal ein Beispiel für eine Methode die eine DataTable liefert die das wahrscheinlich sinnvollere äquivalent wäre.


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:
private const string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=datenbank2.accdb"// nur den Conectionstring verwahren nicht die Connection

public DataTable GetDataTable(string sql)
{
    try
    {
        using (var con = new OleDbConnection(connectionString))
        {
            con.Open();
            using (var adapter = new OleDbDataAdapter(sql, con))
            {
                var dt = new DataTable();
                adapter.Fill(dt);
                return dt;
            }
        }
    }
    catch (Exception a)
    {
        // hier loggen anzeigen etc.
        throw;  // nicht einfach irgendwas tun und die Exception dann schlucken nur der Aufrufer weiß ob das schlimm war wenn die Methode schief geht. der muss dann entscheiden wie es weitergeht.
    }        
}

Für diesen Beitrag haben gedankt: MagratKnoblauch
MagratKnoblauch Threadstarter
Hält's aus hier
Beiträge: 2



BeitragVerfasst: Sa 09.01.16 12:09 
Wow, natürlich. Danke.
Ich bin jetzt nun wirklich kein Profi oder auch nur geübter Anfänger. Ich fange gerade erst an.Das Auslagern ist explizit für ein Projekt, an dem ich mit meinem sehr untalentierten und unwillingen Klassenkameraden arbeiten muss.
Abgabe ist Montag und ich hab meinen Teil getan und muss seine jetzt mit programmieren...stressig. Bin seit ca. 10 Stunden wach und am probieren. Ich hab das gar nicht gesehen dass ich auch individuell in den Methode den die Connection aufrufen kann.

Ich tue das hauptsächlich weil das Auslagern vom Lehrer verlangt wird und ich erst jetzt zum testen kam. Jetzt kann ich vor Abgabe leider auch nicht mehr den Lehrer fragen und war schon echt verzweifelt gestern Nacht.
Vielen Dank. Wirklich gut erklärt.
Ich arbeite das sofort rein!
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 09.01.16 12:17 
Zitat:
Bin seit ca. 10 Stunden wach und am probieren. Ich hab das gar nicht gesehen dass ich auch individuell in den Methode den die Connection aufrufen kann.


Brauchst dich nicht zu entschuldigen. Erfahrung lässt sich nicht durch Schlafmangel ersetzen ;)