Autor Beitrag
mjanz
Hält's aus hier
Beiträge: 11

Win XP, Win Vista
C#(VS 2008), VB (VS 2008)
BeitragVerfasst: Do 28.05.09 12:15 
Hallo Leute,

ich bin in C# ja immer noch Anfänger, arbeite aber gerade an einem ersten größeren Projekt. Mir ist da so eine fixe Idee gekommen, die mich nicht richtig loslässt. Ich möchte gerne eine einzige Klasse schreiben, mit der ich alle benötigten Datenbank abfragen abfrühstücken kann. Das klappt eigentlich auch ganz gut, aber wenn es darum geht Gespeicherte Prozeduren aufzurufen, hört es bei mir auf. Bishar habe ich das immer so gemacht:

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:
     public DataSet Login()
        {

            // Anlegen der Verbindung
            SqlConnection conn = new SqlConnection(connstr);
            // Anlegen des SQL-Befehls
            SqlCommand cmd = new SqlCommand("usp_login", conn);
            // Festlegen des Befehltyps (Gespeicherte Prozedur)
            cmd.CommandType = CommandType.StoredProcedure;

            // Anlegen der benötigten Parameter für die SQL-Abfrage
            SqlParameter paramBenutzerName = new SqlParameter("@benutzername", SqlDbType.VarChar);
            paramBenutzerName.Direction = ParameterDirection.Input;
            paramBenutzerName.Value = strBenutzername;
            cmd.Parameters.Add(paramBenutzerName);

            SqlParameter paramPasswort = new SqlParameter("@passwort", SqlDbType.VarChar);
            paramPasswort.Direction = ParameterDirection.Input;
            paramPasswort.Value = strPasswort;
            cmd.Parameters.Add(paramPasswort);

            SqlParameter paramAktiv = new SqlParameter("@aktiv", SqlDbType.Bit);
            paramAktiv.Direction = ParameterDirection.Input;
            paramAktiv.Value = bAktiv;
            cmd.Parameters.Add(paramAktiv);

            // Anlegen eines Daten-Adapters
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            // Anlegen eines DataSets
            DataSet ds = new DataSet();

            try
            {

                // Öffnen der Verbindung
                conn.Open();
                // Über den Data-Adapter die Tabelle "Login" im 
                // DataSet ds füllen
                da.Fill(ds, "Login");
                // Schließen der Verbindung
                conn.Close();

            }
            catch (Exception ex)
            {
                ds.Tables.Add("Login");
                //System.Windows.Forms.MessageBox.Show(ex.ToString());
                throw;
            }

            return ds;

        }


Dies ist ein Beispiel für einen meiner Aufrufe für eine Gespeicherte Prozedur. Ist bestimmt immer noch nicht ganz elegant, aber es funktioniert. Jetzt möchte ich aber eine allgemeine Funktionen schreiben, der ich einfach nur den Namen der Prozedur mitgebe, die benötigten Parameter (ich dachte irgendwie an ein Array, das man dann durchläuft, um die benötigten Parameter zu übergeben) und die mir dann ein gefülltes DataSet zurückgibt. Leider bekomme ich das irgendwie nicht hin, weil ich nicht weiß, wie ich die Abfrageparameter an die Funktion übergeben könnte. Könnt Ihr mir an dieser Stelle weiterhelfen? Geht das überhaupt? Ich hoffe, Ihr habt verstanden, was ich meine... Tausend Dank im Voraus für Eure Hilfe!

Gruß
mjanz

Moderiert von user profile iconUGrohne: Code- durch C#-Tags ersetzt
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4799
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Do 28.05.09 12:42 
Du könntest entweder die Parameters-Liste als Methodenparameter übergeben oder aber ein Delegate dafür benutzen, so daß du beim Aufruf dann elegant eine anonyme Methode benutzen kannst.

Hier mal meine eigene Methode mittels Delegate:
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:
public class DbUtil
{
    public delegate void ParameterDelegate(SqlParameterCollection parameters);
    public delegate T DataDelegate<T>(IDataRecord reader);

    public static T[] Exec<T>(string sConnection, string sStoredProcedure, ParameterDelegate onParameters, DataDelegate<T> onData)
    {
        if(onData == null)
            return null;

        using(SqlConnection oCon = new SqlConnection(sConnection))
        using(SqlCommand oCmd = new SqlCommand(sStoredProcedure, oCon))
        {
            oCmd.CommandType = CommandType.StoredProcedure;
            if(onParameters != null)
                onParameters(oCmd.Parameters);

            oCon.Open();

            using(SqlDataReader oReader = oCmd.ExecuteReader())
                return Read<T>(oReader, onData);
        }
    }

    public static T[] Read<T>(IDataReader oReader, DataDelegate<T> onData)
    {
        List<T> oList = new List<T>();
        while(oReader.Read())
        {
            oList.Add(onData(oReader));
        }

        return oList.ToArray();
    }
}


Aufruf dann z.B. so:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
return DbUtil.Exec<Test>(ConStr, "dbo.getTest",
                    delegate(SqlParameterCollection parameters)
                    {
                        parameters.Add("@TestId", SqlDbType.Int).Value = 42;
                        // Alternativ: parameters.AddWithValue("@TestId", 42);
                    },
                    delegate(IDataRecord oReader)
                    {
                        return new Test(oReader);
                    });

Du müßtest jetzt die Exec-Methode nur noch Umschreiben auf DataSet, d.h. Fill anstatt mein benutzter DataReader

P.S. Ich hoffe, du kennst dich schon mit Generics aus...

Und 'ParameterDirection.Input' brauchst du nicht explizit anzugeben, da dies der Standardwert ist (reduziert Schreibarbeit -).
mjanz Threadstarter
Hält's aus hier
Beiträge: 11

Win XP, Win Vista
C#(VS 2008), VB (VS 2008)
BeitragVerfasst: Do 28.05.09 12:59 
Wow,

erstmal danke für die schnelle Antwort. Leider weiß ich noch nix über Generics. Damit werde ich mich jetzt mal beschäftigen... Der Code sieht interessant aus. Leider verstehe ich die Systematik nicht ganz. Ich werde mal die MSDN anzapfen und mal schauen, was ich finde... Tausend Dank!

mjanz