Entwickler-Ecke
Datenbanken (inkl. ADO.NET) - Der Name "Settings" ist im aktuellen Kontext nicht vorhanden
ffgorcky - Mo 15.03.10 21:19
Titel: Der Name "Settings" ist im aktuellen Kontext nicht vorhanden
Hallo liebes Forum,
hier noch mal ein eigener Thread für dieses Thema, wo ich immer noch nicht weiter komme:
Ich hatte versucht, durch kopieren und abwandeln des Erstbeitrags des Threads
Datenbanken mit OleDb und SQL [
http://www.c-sharp-forum.de/viewtopic.php?t=76252&start=0&postorder=asc] auch eine Abfrage hinzubekommen.
Aber der Compiler sagt mir: ''Der Name "Settings" ist im aktuellen Kontext nicht vorhanden''.
Also wie muss ich den denn dazu Konstruieren?
Hier mal mein momentaner Versuch, wo er die Meldung bringt:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| public void fuegeEineNeuePersonHinzu(string Name, decimal alter, bool geschlecht) { string sAlter = i16.ConvertToString(alter); comboBoxPersonenAuswahl.Items.Add(Name); comboBoxPersonenAuswahl.SelectedIndex = comboBoxPersonenAuswahl.Items.Count-1; OleDbConnection Con = new OleDbConnection(); Con.ConnectionString = Settings.Default.ConString; Con.Open(); string SQL = "INSERT Name="+Name+" Alter="+alter+" Geschlecht="+geschlecht+" TO
Personen"; OleDbCommand Dat = new OleDbCommand(); Dat.CommandText = SQL; Dat.Connection = Con; OleDbDataReader Reader = Dat.ExecuteReader(); } |
Ich kann leider auch nichts mit
JüThos
Hinweis auf diesen Thread [
http://www.c-sharp-forum.de/viewtopic.php?p=585415#585415] anfangen.
Die Abkürzungen kenne ich ja, aber das bringt mich trotzdem nicht weiter in meinem Problem "Settings".
Ralf Jansen - Mo 15.03.10 22:00
Öffne die Properties deinen Projekts. Dort wirst du unter anderem einen Tab Namens Settings (oder das äquivalent deiner Sprachversion der IDE) finden.
Hier siehst du nun ein Grid mit Einstellungen (Name, Type, Scope, Value) in dem du einfach deinen Connectionstring mit Name = "ConString" und Type = "(Connectionstring)" eintragen kannst. Als Value halt deinen konkreten Connectionstring dort eintragen. Aus den Eintragungen wird dann im folgenden automatisch die Settings Klasse im Properties Namespace erzeugt. Die ConString Property solltest du also eher mit Properties.Settings.Default.ConString ansprechen.
Über dem Grid auf dem Settings Tab solltest du übrigens auch einen Link in die Hilfe mit Detailinformation finden.
JüTho - Mo 15.03.10 23:49
Hallo Ronald,
tut mir leid, wenn ich zusätzlich viel Wasser in den Wein gießen muss; aber du gehst mehrere falsche Wege. Einen Weg, wie der ConnectionString gespeichert werden kann, hat Ralf beschrieben. Dazu kommt folgendes:
1. Eine Connection sollte immer nur für die aktuelle Notwendigkeit erzeugt und geöffnet werden; danach muss sie i.d.R. geschlossen und aufgelöst werden. Das macht man am besten mit einem
using-Block.
2. SQL-Befehle dürfen
niemals per String-Verknüpfung erzeugt werden! Das erzeugt miserablen Code (bei dir: i16.ConvertToString(alter) - was ist das für eine seltsame Konstruktion, wo es doch alter.ToString gibt?!), gibt Probleme mit Formatierungen (dein INSERT-Befehl ist wegen fehlender Hochkommata sowieso ungültig und außerdem völlig falsch aufgebaut) und öffnet Missbrauch Tür und Tor, siehe
Wikipedia: SQL-Injection [
http://de.wikipedia.org/wiki/SQL-Injection].
3. Ein INSERT-Befehl ist etwas zum Speichern, nicht zum Lesen. ExecuteReader ist also abwegig. (Auch hierfür gilt: Schau in die
SDK-Doku, was es für Alternativen gibt).
Ein Alter würde ich übrigens nicht als decimal definieren. Es kommt sicher nicht auf die Genauigkeit von mehr als 15 Stellen an.
Eine vernünftige Lösung sieht kurz gefasst so aus:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| public void fuegeEineNeuePersonHinzu(string name, double alter, bool geschlecht) { comboBoxPersonenAuswahl.Items.Add(name); comboBoxPersonenAuswahl.SelectedIndex = comboBoxPersonenAuswahl.Items.Count-1;
using( OleDbConnection con = new OleDbConnection(Properties.Settings.Default.ConString) ) { string sql = "INSERT INTO Personen (Name, Alter, Geschlecht)" + " VALUES (?, ?, ?);"; OleDbCommand cmd = new OleDbCommand(sql, con); cmd.Parameters.AddWithValue( "@Name", name ); cmd.Parameters.AddWithValue( "@Alter", alter ); cmd.Parameters.AddWithValue( "@Geschlecht", geschlecht ); con.Open(); cmd.ExecuteNonQuery(); } } |
Ist das nicht viel übersichtlicher? con.Close und con.Dispose brauche ich nicht, weil das durch using automatisch erledigt wird. Wenn du willst, kannst du con.Open und den Execute-Befehl in try-catch einbinden und den Rückgabewert von Exec abfragen, um zu erfahren, ob das Einfügen erfolgreich war.
Noch ein paar Hinweise:
OpenBook VC# [
http://openbook.galileocomputing.de/visual_csharp/visual_csharp_25_001.htm] Kap.25 ff. zur Einführung in ADO.NET
Einführung in SQL [
http://de.wikibooks.org/wiki/Einf%C3%BChrung_in_SQL:_Inhaltsverzeichnis], denn du musst schon wissen, wie ein SQL-Befehl auszusehen hat
[Artikelserie] Parameter von SQL Befehlen [
http://www.mycsharp.de/wbb2/thread.php?threadid=66704] dazu, dass und warum mit Parameters gearbeitet werden muss
[Artikel] Ressourcen schonen - Datenbanken richtig öffnen und schließen [
http://www.mycsharp.de/wbb2/thread.php?threadid=22354] als Erläuterung zum using-Block
Schau in die Doku! - Möglichkeiten der Informationsgewinnung [
http://www.mycsharp.de/wbb2/thread.php?threadid=64815]
.NET Richtlinien für Namen [
http://msdn.microsoft.com/de-de/library/ms229002(VS.80).aspx] vor allem wegen Groß- und Kleinschreibung
Gruß Jürgen
ffgorcky - Di 16.03.10 14:29
Hallo Jürgen,
Deine using-Lösung ist gut!
Daran konnte ich mich leider nicht mehr erinnern.
- jetzt bringt er mir aber genau in dieser Zeile 7(in Deinem Quelltext) zum ConString diese Fehlermeldung:
--------------------------------------------------------------------------------------------------------------------------------
"VisuelleWahrnehmung_VersuchNr2.Properties.Settings" enthält keine Definition für "ConString",
und es konnte keine Erweiterungsmethode "ConString" gefunden werden,
die ein erstes Argument vom Typ "VisuelleWahrnehmung_VersuchNr2.Properties.Settings" akzeptiert.
(Fehlt eine Using-Direktive oder ein Assemblyverweis?) 72 90 VisuelleWahrnehmung-VersuchNr2
--------------------------------------------------------------------------------------------------------------------------------
- Also wie binde ich das jetzt ein?
- Oder fehlt da jetzt wirklich auch noch ein using-Verweis?
JüTho - Di 16.03.10 15:35
Ralf hat beschrieben, wie der ConnectionString registriert werden kann; er hat den Namen ConString vorgeschlagen. Er hat dir aber nicht über die Schultern geschaut, was du tatsächlich geschrieben hast. Du musst denselben Namen benutzen, den du in den Properties angegeben hast.
Das ist aber eine Fehlermeldung, der du selbst nachgehen kannst und musst.
Jürgen
ffgorcky - Di 16.03.10 15:37
Und ich habe eine Komponente, die mir decimal für das Alter zurückgibt:
numericUpDownAlter.Value
Wie wandele ich das in double um?
JüTho - Di 16.03.10 15:41
ffgorcky hat folgendes geschrieben : |
Wie wandele ich das in double um? |
1.
SDK-Doku/MSDN/Hilfe - Stichwort: Was gibt es zur
decimal-Klasse?
2. Wie kann man etwas in etwas umwandeln? Wie kann das in Englisch heißen?
Etwas mehr Eigeninitiative bitte! Jürgen
JüTho - Di 16.03.10 16:58
Nicht so kompliziert denken, sondern viel primitiver: umwandeln in double oder nach double. Klingelt's jetzt?
Noch'n Tipp: Welche Methode gibt es für jede Klasse? Was macht die? Hilft diese Erkenntnis weiter bei dem Problem mit double?
Und natürlich das, was ich schon sagte: selbst in der SDK-Doku/MSDN/Hilfe unter decimal-Klasse / Alle Member nachlesen.
Jürgen
ffgorcky - Di 16.03.10 18:29
Ja, ich habe die Lösung gefunden!:
C#-Quelltext
1:
| Convert.ToDouble(numericUpDownAlter.Value) |
:-)
JüTho - Di 16.03.10 19:14
Das ist eine von 83 anderen. Was hältst du davon:
C#-Quelltext
1:
| alter = Decimal.ToDouble(numericUpDownAlter.Value); |
Versteh mich nicht falsch: Das ist jetzt weitgehend Geschmackssache; deine und meine Lösung machen faktisch dasselbe (nicht nur das gleiche). Es gibt aber eine Reihe von Situationen, wo die
Convert-Methoden mindestens äußerst ungünstig sind; deshalb empfehle ich, darauf möglichst zu verzichten.
Der entscheidende Punkt ist: Du hast
ToDouble als Lösung gefunden; das kannst du hoffentlich auf künftige Bedürfnisse übertragen und sofort direkt in der SDK-Doku nach einem solchen Stichwort suchen.
Viel Erfolg weiterhin! Jürgen
Kha - Di 16.03.10 20:17
Oder auch (double)numericUpDownAlter.Value - die Qual der Wahl ;) .
ffgorcky - Di 23.03.10 12:46
So, entschuldigt Leute, dass ich vom Titel-Thema abgewichen bin.
Noch mal eine Frage zu diesem eigentlichen Problem:
Ich habe das hier jetzt als Verbindungszeichenfolge im Bereich Anwendung unter dem Namen "ConString" gespeichert:
Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\NP-Test.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True
und in meinem Entwicklungs-Ordner habe ich auch genau diese Datei liegen.
Aber während der Laufzeit kommt dann immer noch bei dieser Prozedur:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| public void fuegeEineNeuePersonHinzu(string name, double alter, bool geschlecht) { comboBoxPersonenAuswahl.Items.Add(name); comboBoxPersonenAuswahl.SelectedIndex = comboBoxPersonenAuswahl.Items.Count - 1; using (OleDbConnection con = new OleDbConnection(Properties.Settings.Default.ConString)) { string sql = "INSERT INTO Personen (Name, Alter, Geschlecht)" + " VALUES (?, ?, ?);"; OleDbCommand cmd = new OleDbCommand(sql, con); cmd.Parameters.AddWithValue("@Name", name); cmd.Parameters.AddWithValue("@Alter", alter); cmd.Parameters.AddWithValue("@Geschlecht", geschlecht); con.Open(); cmd.ExecuteNonQuery(); } } |
in der using-Zeile der Fehler:
Zitat: |
In ConnectionString wurde kein OLE DB Provider abgegeben.
Anwendungsbeispiel: 'Provider=SQLOLEDB;'. |
JüTho - Di 23.03.10 13:56
Es ist eben ein Unterschied, welcher DbProvider verwendet wird. Jeder Provider hat seine speziellen Informationen, die er für den ConnectionString braucht.
* Oledb => allgemeiner DB-Zugriff => spezielle Informationen wie "Provider=SQLOLEDB" werden benötigt
* Sql => spezieller DB-Zugriff => nur der Zugriff selbst muss geregelt werden
Wenn du "Data Source=.\SQLEXPRESS" angibst, verwendest du offensichtlich den MS-SQL-Server (und nicht Access). Dann brauchst du die
Sql-Klassen statt der Oledb-Klassen.
Die verschiedenen Varianten mit möglichen Verbindungsdaten findest du u.a. unter
ConnectionStrings [
http://www.connectionstrings.com/default.aspx]. Du kannst auch den jeweiligen XxxConnectionStringBuilder ausprobieren, welche Teile eingegeben werden müssen, damit einen ConnectionString erzeugen lassen und diesen speichern.
Gruß Jürgen
PS. Es ist möglich, mit Oledb auf den SQL-Server zuzugreifen, aber keinesfalls zu empfehlen. Wenn du für deine Stereo-Anlage zuhause die Auswahl hast zwischen einem hochwertigen Kopfhörer und primitiven Ohrstöpseln, wirst du auch der Qualität den Vorzug geben.
ffgorcky - Mo 03.05.10 09:17
Entschuldigt, dass ich hier leider irgendwie nicht weiterkomme.
Im Moment sieht meine Prozedur so aus:
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:
| public void fuegeEineNeuePersonHinzu(string name, double alter, bool geschlecht,bool selbstZusammengebastelteVersionZurUnterscheidungVonDerForumsLösung) { comboBoxPersonenAuswahl.Items.Add(name); comboBoxPersonenAuswahl.SelectedIndex = comboBoxPersonenAuswahl.Items.Count - 1; SqlConnectionStringBuilder conBuilder = new SqlConnectionStringBuilder(); using (SqlConnection con = new SqlConnection(conBuilder.ConnectionString)) { con.ConnectionString = "Data Source=(local);" + "Initial Catalog=NP-Test;" + "Integrated Security=sspi"; string sql = "INSERT INTO Personen (Name, Alter, Geschlecht)" + " VALUES (?, ?, ?);"; SqlCommand cmd = new SqlCommand(con.ConnectionString); cmd.Parameters.AddWithValue("@Name", name); cmd.Parameters.AddWithValue("@Alter", alter); cmd.Parameters.AddWithValue("@Geschlecht", geschlecht); try { con.Open(); try { cmd.ExecuteNonQuery(); con.Close(); } catch (SqlException) { MessageBox.Show("Der Datenbank-Eintrag hat bei geöffneter Datenbank nicht geklappt."); } } catch (SqlException) { MessageBox.Show("Der Datenbank-Eintrag hat nicht geklappt. - Die Datenbank konnte nicht geöffnet werden."); } }
} |
Sie funkioniert aber so nicht.
Da erscheint immer noch die Fehlermeldung ..."
Die Datenbank konnte nicht geöffnet werden.".
Kann mir jemand sagen, warum solch eine Meldung kommt?
Heißt das etwa, dass das Datenbank-Programm nicht aktiv ist?
Oder wie kann ich denn mal eine kleine Abfrage machen, in der ich feststellen kann, woran es genau liegt?
JüTho - Mo 03.05.10 09:47
Hallo,
eines deiner Probleme ist, dass du verschiedene Dinge mischst. (Das liegt natürlich auch an den vielen Versuchen.)
1. Beim
SqlConnectionStringBuilder werden die einzelnen Bestandteile (DataSource, InitialCatalog usw.) eingetragen. Den ConnectionString setzt der Builder daraus zusammen, dann wird er abgerufen.
conBuilder.ConnectionString sollte also niemals links vom Gleichheitszeichen stehen; üblicherweise wird es direkt in den Konstruktor-Aufruf der Connection gesetzt.
Letzteres machst du zwar, aber die Zuweisung der Einzelteile hast du auskommentiert. Also kann im ConnectionString nichts Sinnvolles mehr enthalten sein; also kann keine Datenbank geöffnet werden.
2. Folgendes ist "doppelt gemoppelt":
C#-Quelltext
1: 2: 3:
| con = new SqlConnection(conBuilder.ConnectionString) con.ConnectionString = "Data Source=(local);" + "Initial Catalog=NP-Test;" + "Integrated Security=sspi"; |
3. Hier nimmst du nicht den SQL-Befehl:
C#-Quelltext
1:
| SqlCommand cmd = new SqlCommand(con.ConnectionString); |
4. Beim Sql-Provider müssen die Parameter mit Namen benutzt werden; siehe in der Artikelserie zu den SQL-Parametern den 3. Beitrag.
ffgorcky hat folgendes geschrieben : |
Oder wie kann ich denn mal eine kleine Abfrage machen, in der ich feststellen kann, woran es genau liegt? |
Es empfiehlt sich, zuerst mit dem Management Studio eine Verbindung herzustellen, damit der ConnectionString bekannt ist und übernommen werden kann. Danach kann man mit einem SELECT-Befehl experimentieren, um Werte abzurufen und anzuzeigen. Wenn das funktioniert, kommen UPDATE- und INSERT-Befehle an die Reihe.
Wenn du bei
catcheine Exception notierst, dann benutze sie auch mit
ex.ToString in der Meldung (das liefert die meisten Informationen).
Gruß Jürgen
PS. Der Datenbank-Zugriff hat mit dem ursprünglichen Problem eigentlich nichts mehr zu tun. Vielleicht solltest du einen Moderator bitten, die Diskussion an einer passenden Stelle zu trennen.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!