*Markus: Wie WHERE-Bedingung in C# übergeben?

Hallo,

wie sieht es in C# aus, wenn man MS-Access-Abfragen nach einem bestimmten Kriterium mit WHERE macht?
Meine bisherigen Versuche sehen so aus:

OleDbCommand command = new OleDbCommand("SELECT vorname, geburtsjahr FROM person1 WHERE geschlecht = ?", connection);
try   {
command.Parameters.Add(new OleDbParameter("@geschlecht", OleDbType.Char) );
}
catch (OleDbException exc)  {
    Console.WriteLine("Fehler: " + exc.Message);
}
command.Parameters["@geschlecht"].Value = s;

..wobei command.Parameters.Add("@geschlecht", OleDbType.Char ); ebenfalls nichts bewirkt.
Ich weiß jetzt gar nicht, ob es wieder mal ein Mono-Bug ist, da es schon bei ArrayList Probleme macht, wodurch die Fehlermeldung auch nicht besonders aufschlussreich ist:

Error at Line : syntax error near ?

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object
  at DataReader.PrintSex (System.String s) [0x00000]
  at DBManager.PrintSex (System.String sex) [0x00000]
  at Menu.showMenu () [0x00000]
  at Datenbankprogramm.MainClass.Main (System.String[] args) [0x00000]

Wenn ich eine zusätzliche Catch-Klausel einfüge ändert sich an der Fehlermeldung nichts.
Wo liegt der Fehler?

Markus

  1. OleDbCommand command = new OleDbCommand("SELECT vorname, geburtsjahr FROM person1 WHERE geschlecht = ?", connection);

    Dieses Fragezeichen bedeutet ein serverseitiges oder clientseitiges "Prepare". Es ist nicht gesagt, dass das gekonnt wird von der Prozedur.

    Ich weiß jetzt gar nicht, ob es wieder mal ein Mono-Bug ist, da ...

    Problemisolierung ist Dein Job. Diese ist _immer_ moeglich.

    Wo liegt der Fehler?

    Und natuerlich Doku lesen. Was sagt denn Dr.Doku zu dieser Pathologie?

    1. Dieses Fragezeichen bedeutet ein serverseitiges oder clientseitiges "Prepare". Es ist nicht gesagt, dass das gekonnt wird von der Prozedur.

      Es stammt aus einem funktionierenden Beispiel.

      Ich weiß jetzt gar nicht, ob es wieder mal ein Mono-Bug ist, da ...

      Problemisolierung ist Dein Job. Diese ist _immer_ moeglich.

      Möglich ist ohnehin immer alles.

      Und natuerlich Doku lesen. Was sagt denn Dr.Doku zu dieser Pathologie?

      Ob Mono ein Bug hat, wirst du wohl kaum in einer Doku finden.

  2. Hallo *Markus,

    versuchs doch mal mit WHERE geschlecht = @geschlecht

    Gruß Mia

    1. Hallo,

      ich verstehe das nicht ganz. Zur Probe versuchte ich mal ein ...

      OleDbDataReader reader = null;
      OleDbCommand command = new OleDbCommand("SELECT vorname, geburtsjahr FROM person1 WHERE geschlecht = M", connection);
      OpenConnection();
      reader = command.ExecuteReader();

      ....aber der Fehler blebt noch immer. Dabei versuchte ich M auch unter einfache Anfürhungszeichen zu setzen.

      Markus

      1. Ok bei geschlecht = 'M' funktioniert es dann, wenn ich zusätzlich eine NullReferenceException fange, nur auf die Syntax der Parameterübergabe komme ich nicht drauf. Bei meinen Recherchen fand ich das Fragezeichen. Allerdings hört ich auch wiederum, dass man bei Access den Klammeraffen stattdessen verwendet, aber das Programm bleibt davon unbeeindruckt.

        1. Hallo *Markus,

          hast Du es dann mal mit @geschlecht statt ? versucht und dann bei der Parameterübergabe auch mit @geschlecht. Soweit ich weiß wird der String im SELECT gesucht und durch den neuen Wert ersetzt.

          Gruß Mia

          1. Hallo,

            ich habe schon alles mögliche versucht, aber selbst in der Microsoft-Referenz sieht die Syntax so aus, wie ich sie auch anwende:

            public String[,] PrintSex(string s)   {
               String[,] datensatz = new String[6,2];
             try  {
               OleDbCommand command = new OleDbCommand("SELECT vorname, gebJahr FROM person1 WHERE geschlecht = ?", connection);
             try   {

            command.Parameters.Add("@geschlecht", OleDbType.Char).Value = s;

            }

            catch (OleDbException exc)  {

            Console.WriteLine("Fehler: " + exc.Message);

            }
             OpenConnection();
                   OleDbDataReader reader = command.ExecuteReader();
                   int i = 0;
                   while (reader.Read())   {
                            for (int j = 0; j < 2; j++)
                                datensatz[i,j] = reader.GetValue(j).ToString();
                                 i++;
                         }
                    }
             catch (OleDbException ex)  {
              Console.WriteLine("Fehler: " + ex);
                   }
             catch (InvalidCastException cex)   {
               Console.WriteLine("Fehler: " + cex);
             }
             catch (NullReferenceException nre)   {
                Console.WriteLine("Fehler: " + nre);
                   }
            CloseConnection();

            Warum aber immer diese Meldung kommt ist mir schleierhaft:

            Error at Line : syntax error near ?
            Fehler: System.NullReferenceException: Object reference not set to an instance of an object
              at DataReader.PrintSex (System.String s) [0x00000]

            Ich glaub allmählich, dass Mono wieder mal irgend etwas nur unzureichend implementiert hat, sodass diese Funktion fehlerhaft ist, was auch der Grund ist, warum ich hier keine Collection anwenden kann, und zur Probe auf ein mehrdimensionales Array ausweichen muss.

            Markus

            1. Hallo *Markus,

              versuche mal, die Strings vorher anzulegen, also

              datensatz[i,j] = new string();
              datensatz[i,j] = reader.GetValue(j).ToString();

              Nur durch die Definition des Arrays sind die einzelnen Elemente noch angelegt. Und die Fehlermeldung besagt ja genau so etwas.

              Gruß Mia

              1. Hallo,

                datensatz[i,j] = new string();
                datensatz[i,j] = reader.GetValue(j).ToString();

                Nur durch die Definition des Arrays sind die einzelnen Elemente noch angelegt. Und die Fehlermeldung besagt ja genau so etwas.

                Bei der Ausgabe aller Einträge gehe ich zwar genauso vor, wie in dieser Methode, aber ich probierte es zur Sicherheit trotzdem aus. datensatz[i,j] = new string(); ruft die Fehlermeldung....

                No overload for method string' takes 0' arguments(CS1501)

                ...hervor. Außerdem sind am Anfang der Methode bei der Erzeugung des Arrays die Stringreferenzen im Array bereits da. Sie zeigen nur noch auf keine Stringobjekte. Ich wüsste jetzt auch nicht, was ".... = new string();" bringen würde, selbst wenn es funktionieren würde.
                Trotzdem danke für den Tipp.

                P.S.
                Mittlerweile fand ich übrigens heraus, dass List<> wohl doch implementiert ist, aber erst mit der Mono-2.0-Runtime.

                Markus

                1. Hallo *Markus,

                  wie sieht es denn mit den Feldern aus, die Du liest (vorname und gebJahr). Bist Du sicher, dass nicht eines davon irgendwo mal "null" ist in der Datenbank?

                  Gruß Mia

                  1. Hallo,

                    wie sieht es denn mit den Feldern aus, die Du liest (vorname und gebJahr). Bist Du sicher, dass nicht eines davon irgendwo mal "null" ist in der Datenbank?

                    Bei den Feldern ist stets alles befüllt. Ein NULL-Wert ist also nirgendwo vorhanden. Ich glaub nicht, dass es noch etwas gibt, was ich noch nicht durchtestete. Ich müsste den Code mal auf einem Windows-System testen, damit ich Gewissheit habe, ob es wirklich an Mono liegt.

                    Markus

      2. Hello,

        Ich kenne mich mit den C-Objekten nicht aus, könnte mir aber vorstellen, dass ein vollständiges Query übergeben werden muss. Dann fehlt einfach nur ein Semikolon am Ende.

        OleDbCommand command = new OleDbCommand("SELECT vorname, geburtsjahr FROM person1 WHERE geschlecht = 'M';", connection);

        Harzliche Grüße vom Berg
        http://www.annerschbarrich.de

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau

        1. Hallo,

          Ich kenne mich mit den C-Objekten nicht aus, könnte mir aber vorstellen, dass ein vollständiges Query übergeben werden muss. Dann fehlt einfach nur ein Semikolon am Ende.

          Wäre zwar ein heißer Tipp gewesen, da ich daran noch nicht dachte, aber der Semikolon ruft einen Fehler hervor. Ich frage mich allmählich, welche Eigenheiten Microsoft hier wieder mal ausgebrütet hat.
          Es ist auch sehr schwer an nützliche Informationen zu kommen, da ich nicht weiß, ob das "richtiges" SQL ist, und wenn ja, wie es in C# anzuwenden ist, da man auch hier nur wenig nützliches findet.

          Markus

          1. Hello Markus,

            vielleicht hilft das weiter:

            http://www.csharphelp.com/archives/archive70.html

            Harzliche Grüße vom Berg
            http://www.annerschbarrich.de

            Tom

            --
            Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
            Nur selber lernen macht schlau

            1. Hi,

              nun ein normaler SELECT-Query funktioniert ja, nur sieht's eben bei der Parameterübergabe offensichtlich ganz anders aus.

              Markus

              1. nun ein normaler SELECT-Query funktioniert ja, nur sieht's eben bei der Parameterübergabe offensichtlich ganz anders aus.

                Wie lautet denn der Fehlercode 1. bei Deiner Abfrage 2. bei einem gefuellten WHERE also mit Hochkömmata und Vergleichswert?

                1. Wie lautet denn der Fehlercode 1. bei Deiner Abfrage 2. bei einem gefuellten WHERE also mit Hochkömmata und Vergleichswert?

                  Das Lustige dabei ist ja, dass es mit 'M' statt dem Fragezeichen funktioniert.
                  Ich glaube, dass ich alles durchgetestet, was es zum Durchtesten gibt. Mittlerweile glaube ich auch, dass der Code gar nicht fehlerhaft ist, sondern Mono. Vor allem gibt es weder einen Debugger, noch eine Zeilennummerierung bei dieser Fehlermeldung.

                  Markus

                  1. Hallo Markus!

                    Das Lustige dabei ist ja, dass es mit 'M' statt dem Fragezeichen funktioniert.

                    Das ? steht als Platzhalter für genau ein Zeichen, in dieser Schreibweise für ein integer, also für 1 (= männlich) oder 2 (= weiblich). Du fragst aber 'M' als string ab.

                    Beste Grüsse
                    Richard

                    1. Hallo,

                      Das ? steht als Platzhalter für genau ein Zeichen, in dieser Schreibweise für ein integer, also für 1 (= männlich) oder 2 (= weiblich). Du fragst aber 'M' als string ab.

                      Das Fragezeichen ist doch ein Platzhalter für eine Variable, was ja auch logisch erscheint, da sonst  der Programmierer ja schon im vorhinein wissen müsste, was jemand als Variable übergibt.

                      Markus

                      1. Hallo Markus!

                        Das ? steht als Platzhalter für genau ein Zeichen, in dieser Schreibweise für ein integer, also für 1 (= männlich) oder 2 (= weiblich). Du fragst aber 'M' als string ab.
                        Das Fragezeichen ist doch ein Platzhalter für eine Variable, was ja auch logisch erscheint, da sonst  der Programmierer ja schon im vorhinein wissen müsste, was jemand als Variable übergibt.

                        Dann solltest du anstelle des ? auch eine Variable einsetzen.

                        Beste Grüsse
                        Richard

                        1. Hallo Richard,

                          Das Fragezeichen ist doch ein Platzhalter für eine Variable, was ja auch logisch erscheint, da sonst  der Programmierer ja schon im vorhinein wissen müsste, was jemand als Variable übergibt.

                          Dann solltest du anstelle des ? auch eine Variable einsetzen.

                          nein, natürlich nicht. Das ist ja eigentlich Sinn und Zweck der Aktion. Solche parametrisierten Abfragen haben vor allem zwei Vorteile:

                          1. Man muss sich nicht um das datenbankspezifische Escapen der Parameter kümmern.
                          2. Die Abfrage kann ggf. vorkompiliert werden und bei mehrfacher Ausführung
                             mit unterschiedlichen Parametern vom Caching profitieren.

                          In VBA funktioniert das, was Markus vorhat, problemlos.

                          Freundliche Grüße

                          Vinzenz

                          1. Hallo Vinzenz!

                            In VBA funktioniert das, was Markus vorhat, problemlos.

                            Warum VBA? Und warum funktioniert es nicht?

                            Ich habe mich ehrlich gesagt nur um die WHERE-Klausel der SELECT-Abfrage gekümmert. Und die halte ich so nicht für funktionsfähig.

                            Beste Grüsse
                            Richard

  3. Ich habe es jetzt auf Windows probiert, wo es auch funktioniert. Es ist also ein Mono-Problem.