Laden...

Sql Query an params Variablen binden

Erstellt von Martinar vor 12 Jahren Letzter Beitrag vor 12 Jahren 5.595 Views
M
Martinar Themenstarter:in
55 Beiträge seit 2010
vor 12 Jahren
Sql Query an params Variablen binden

verwendetes Datenbanksystem: <SQL sServer2008 Express>

Hallo Leute,

vor eineigen Tagen hatte ich folgende Funktion gebaut und glaube auch noch, dass sie funktioniert hatte:

bool bWert
int nWert;
string sWert

DB.SQL("Sql-Statement",bWert,nWert,sWert) ;

Die drei Werte werden als params Variablen übergeben.

Nun kommt mein Problem, leider habe ich von dieser Funktion keine Sicherung gemacht und weiß auch nicht mehr, wie ich das aufgebaut habe und ob das überhaupt ging,
dass man aus einem DataReader,Werte an params Variable binden kann.

Ich habe eine ähnliche Funktion für Textboxen und da funktioniert es,dass ich die Ergebnisse an beliebig viele Textboxen ausgeben kann

Eigentlich bäruche ref params ,aber dasgibt es ja nicht.

c
2.120 Beiträge seit 2010
vor 12 Jahren

? ? ?

Mal ganz ehrlich, ich krieg das was du da schreibst in überhaupt keinen Zusammenhang. Tut mir leid, bitte nochmal.

M
Martinar Themenstarter:in
55 Beiträge seit 2010
vor 12 Jahren

Ok sorry, kein Problem!
Evtl hilft ein bisschen Code:

public bool SQL(string psSql, params TextBox[] pTextBox)
            {
                SqlCommand eCmd = null;
                SqlDataReader eReader = null;
                int enBox;

                eCmd = gCon.CreateCommand();
                eCmd.CommandText = psSql;

                enBox = pTextBox.GetLength(0);
                try
                {
                    eReader = eCmd.ExecuteReader();
                    if (eReader.FieldCount == enBox)
                    {
                        if (eReader.HasRows)
                        {
                            while (eReader.Read())
                            {
                                for (int en = 0; en < eReader.FieldCount; en++)
                                {
                                    pTextBox[en].Text = eReader[en].ToString();
                                }
                                
                            }
                        }
                    }
                    eReader.Close();
                    return true;
                }
                catch
                {
                    if (eReader == null)
                    {
                    }
                    else if (!eReader.IsClosed || eReader != null)
                    {
                        eReader.Close();
                    }
                    else
                    {
                    }
                    return false;
                }
            }

Das Funktioniert für Textboxen und nnun möchte so eine Funktion schreiben für einen SQL-String, der dann noch unterscheidet, ob es bool, int oderstring ist.

1.552 Beiträge seit 2010
vor 12 Jahren

Uou....was machst du da??
Textboxen werden zur Anzeige und nicht zur Logic benutzt. Führ den SQL-Command aus, speichere das Ergebnis irgendwo und zeige es dann in deiner GUI an, und kombiniere nicht das Auslesen des Commands direkt mit den GUI-Elementen. Dies ist ganz hässlich und gefährlich, mal davon abgesehen dass dir die GUI so komplett blockiert wird sollte der Command mal längere Zeit beim ausführen benötigen

Gruß
Michael

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

M
Martinar Themenstarter:in
55 Beiträge seit 2010
vor 12 Jahren

Damit kann sowas ausführen:

DB.SQL("SELECT WERNR,WERUSER FROM FIRMA WHERE WERNR=1", Textbox1, TExtBox2);

M
Martinar Themenstarter:in
55 Beiträge seit 2010
vor 12 Jahren

Hat denn Keiner eine Idee,warum das für die Textboxen geht und für unterschiedliche Werte nicht?

1.378 Beiträge seit 2006
vor 12 Jahren

Weil TextBoxen Referenztypen sind und deine Variablen Wertetypen. -> Grundlagen

Zusätzlich:

  • Verwende ordentlich Variablennamen: Naming Convention
  • Verwende das using Konstrukt und verwerfe damit alle Objekte die IDisposable implementieren und nicht mehr gebraucht werden.(siehe DbConnection, DbCommand, DbDataReader in deiner Methode)
  • Wenn deine Abfrage mehr als ein Result liefert hast du nur den letzten Wert in deinen TextBoxen stehen.
  • "eReader.HasRows" ist unnötig, da die while schleife das mit "reader.Read()" eh schon prüft.

Aber ganz abgesehen von diesen Kleinigkeiten ist das grausamstes Design und deine Frage sollte nicht lauten, wie kann ich es trotzdem zum laufen bringen, sondern wie kann ichs besser machen. 😉

Lg XXX

1.552 Beiträge seit 2010
vor 12 Jahren

Es werden die Textboxen nebenbei auch noch mit dem Letzten Wert des DataReaders gefüllt, da du diese immer und immer wieder überschreibst. Un es wird ein IndexOutOfBound geworfen falls dein SQL-Reader mehr Columns hat als du TextBoxen als Parameter übergeben hast.

Grundsätzlich werden SQLCommand, SqlDataReader in using Blöcke geschrieben.


if (eReader == null)
{}
else if (!eReader.IsClosed || eReader != null)
{
    eReader.Close();
}
else
{}
return false;

die erste eReader == null Abprüfung lässt sich vermeiden wenn du zweitere Abfrage umdrehst. Und sie lässt sich verhindern wenn du einen using Block schreibst.
M.E. ist dies wirklich schlechter Code und sollte tunlichst vermieden werden.

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

M
Martinar Themenstarter:in
55 Beiträge seit 2010
vor 12 Jahren

Vielen Dank für die Tipps^^

Kann ich den aus den Wertetypen irgendwie Referenztypen machen?

M
Martinar Themenstarter:in
55 Beiträge seit 2010
vor 12 Jahren

Es werden die Textboxen nebenbei auch noch mit dem Letzten Wert des DataReaders gefüllt, da du diese immer und immer wieder überschreibst. Un es wird ein IndexOutOfBound geworfen falls dein SQL-Reader mehr Columns hat als du TextBoxen als Parameter übergeben hast.

Grundsätzlich werden SQLCommand, SqlDataReader in using Blöcke geschrieben.

  
if (eReader == null)  
{}  
else if (!eReader.IsClosed || eReader != null)  
{  
    eReader.Close();  
}  
else  
{}  
return false;  

die erste eReader == null Abprüfung lässt sich vermeiden wenn du zweitere Abfrage umdrehst. Und sie lässt sich verhindern wenn du einen using Block schreibst.
M.E. ist dies wirklich schlechter Code und sollte tunlichst vermieden werden.

Das Prüfe ich ja, ob FieldCount == Array.Length

M
Martinar Themenstarter:in
55 Beiträge seit 2010
vor 12 Jahren

achja, da soll auch immer nur ein Datensatz rauskommen.

1.552 Beiträge seit 2010
vor 12 Jahren

Kann ich den aus den Wertetypen irgendwie Referenztypen machen? Mach dass deine Methode das Ergebnis zurückgibt.
Das Prüfe ich ja, ob FieldCount == Array.Length

Stimmpt. Dann muss ich dies wohl übersehen haben.

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

M
Martinar Themenstarter:in
55 Beiträge seit 2010
vor 12 Jahren

Du hast ja recht,
es muss aber bool bleiben.
Gibt es denn keine Möglichkeit Referenztypen da reinzubauen.

1.552 Beiträge seit 2010
vor 12 Jahren

Wenn es unbedingt 2 Rückmeldungen braucht dann helfen dir entweder ref , out oder Delegaten weiter.
Wobei ich Delegaten bevorzugen würde.

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

M
Martinar Themenstarter:in
55 Beiträge seit 2010
vor 12 Jahren

Aber das geht doch nicht mit params oder?
Kann man da etwas drumherum modeln?^^

Kannst du mir evlt, den head so ummodeln,dass ich beliebig viele Referenztypen übergeben kann, weil mit delegaten kenne ich mich nicht so aus.

Wäre echt super...

1.552 Beiträge seit 2010
vor 12 Jahren

Kann man da etwas drumherum modeln?^^

Modeln heißt doch etwas schöner machen und nicht schlechter. Je mehr mit den param gearbeitet wird, desto mehr müssen diese auf Richtigkeit abgeprüft werden, schon mal dadurch dass du verschiedene Objecte übergeben willst. Nimm und unsere Tipps und Warnungen zu Herzen und schreibe diese Methode anders. Du machst dir nur unnötig über Probleme Gedanken die normalerweise wenn der Code anständig geschrieben wäre nicht existieren würden.

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

M
Martinar Themenstarter:in
55 Beiträge seit 2010
vor 12 Jahren

Mhhhhhhhhhh ok Schade, danke für euere Antworten.

1.552 Beiträge seit 2010
vor 12 Jahren

Ich wollte damit nicht sagen dass es nicht funktioniert wie du es machst, aber es macht keinen Sinn. Später wenn du vielleicht in dieser Methode auf einen Fehler aufmerksam wurdest, würdest du dir wünschen ihn die Methode nicht so kompliziert geschrieben zu haben. Sei es auch nur darum wenn du fehlerhaft params vertauscht.

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

1.378 Beiträge seit 2006
vor 12 Jahren

"modeln" verstehe ich hier eher als murksen... 😃

Hier ein Ansatz, wie dus zB. anders machen könntest:



        public class User
        {
            public int ID { get; set; }
            public string Name { get; set; }
        }

        public class UserRepository
        {
            public bool TryGetUser(int userId, out User user)
            {
                using (SqlConnection connection = CreateConnection())
                {
                    using (SqlCommand command = connection.CreateCommand())
                    {
                        command.CommandText = "SELECT WERNR,WERUSER FROM FIRMA WHERE WERNR=@userId";

                        command.Parameters.AddWithValue("userId", userId);

                        using (SqlDataReader dataReader = command.ExecuteReader())
                        {
                            if (!dataReader.Read())
                            {
                                user = null;
                                return false;
                            }

                            user = new User
                            {
                                ID = dataReader.GetInt32(0),
                                Name = dataReader.GetString(1)
                            };
                            return true;
                        }
                    }
                }
            }
        }

Lg XXX

M
Martinar Themenstarter:in
55 Beiträge seit 2010
vor 12 Jahren

Ja ich finde das ja gut, dass ihr mir helfen wollt.

Aber ich brauche diese Sache nur, um es einmal zu testen ob es geht.
Ob ich es je verwenden werde, ist etwas anderes, da werde ich mich dann an deine Tipps halten.

Kannst Du es mal ummodeln, nur wenn es nicht zu viel Arbeit macht

@xxxprod: Wowwwwww,das sieht echt gut aus, ich brauche es aber nur ein Mal für meine Sache,auch wenn es sehr DIRTY ist

1.378 Beiträge seit 2006
vor 12 Jahren

Nein es gibt nichts zum ummodeln. Das was du willst, so wie du es willst, geht einfach nicht.

Lg XXX

M
Martinar Themenstarter:in
55 Beiträge seit 2010
vor 12 Jahren

Man kann also kein SQL-Result in beliebig viele String einlesen?

1.378 Beiträge seit 2006
vor 12 Jahren

Das ist jetzt eine andere Frage die nichts mit der ursprünglichen zu tun hat.

Was nicht möglich ist, ist per Params variablen referentiell übergeben.

Hier eine alternative, die die selektierten Spalten als strings zurück gibt:



        public bool GetValues(string sqlCommand, out string[] values)
        {
            using (SqlConnection connection = CreateConnection())
            {
                using (SqlCommand command = connection.CreateCommand())
                {
                    command.CommandText = sqlCommand;

                    using (SqlDataReader dataReader = command.ExecuteReader())
                    {
                        if (!dataReader.Read())
                        {
                            values = new string[0];
                            return false;
                        }

                        values = new string[dataReader.FieldCount];
                        for (int i = 0; i < dataReader.FieldCount; i++)
                        {
                            var value = dataReader.GetValue(i);
                            values[i] = value == DBNull.Value ? null : value.ToString();
                        }
                        return true;
                    }
                }
            }
        }

Lg XXX

M
Martinar Themenstarter:in
55 Beiträge seit 2010
vor 12 Jahren

Danke für deinen Versuch xxxprod...

Aber ich dachte das sowas möglich wäre:


public class cUser
{

private int mnWert1;
private bool mbWert2;
private string msWert3;

private void Funktion()
{
cDB DB = new DB();
DB.SQL("SELECT WERNR,WERT2,WERT3 FROM FIRMA WHERE WERNR =1", mnWert1,mbWert2,msWert3);
}

} 

Weil mein Grundgedanke war eine SELECT INTO Variablen zu schreiben...
Aber gut, wenn das nicht möglich ist.

Wieso hat man diese "params" so beschränkt?
Kann mann denn ein SELECT INTO Variablen realisieren???