Hallo zusammen,
ich hätte da mal eine dumme Anfängerfrage. Habe schon gegoogelt, aber ich finde nichts dazu...
Und zwar kommt, sobald ich "Art" hinzufüge immer der Fehler "Datenkonflikt in Kriterienausdruck". Was ist damit genau gemeint ? Könntet ihr mir auf die Sprünge helfen was ich falsch mache ? Lasse ich nur den "Titel" drin fügt er mir das automatisch in die Datenbank ohne Probleme.
Benutze bei der Datenbank Access und Ausgabe erfolgt in einer Datagridview.
Bin relativ am Anfang mit Datenbanken. Deshalb blicke ich da noch nicht so durch...
Vielen Dank !
private void cmd_speichern_Click(object sender, EventArgs e)
{
try
{
con.Open(); // Verbindung herstellen zur Datenbank
OleDbCommand cmd = con.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = @"insert into Aufgabe (Titel, Art) values ('" + txt_titel.Text + "','" + txt_art.Text + "')";
cmd.ExecuteNonQuery();
MessageBox.Show("Auswahl hinzufügen erfolgreich");
con.Close();
this.Close(); //Schließen des zweiten Fensters
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
}
Deutsche Fehlermeldung sind nicht immer optimal, daher empfiehlt es sich immer auf das deutsche SDK zu verzichten.
Der Fehler wird aber womöglich daher kommen, weil Du den SQL Befehl leider genau so zusammen baust, wie man es nicht tun soll 😉
=> [Artikelserie] SQL: Parameter von Befehlen
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Grund ist wahrscheinlich dass Art keinen String haben will, aber du übergibst einen.
Testweise kannst du die ' ' um txtArt.Text weglassen und schauen obs dann funktioniert.
Dann aber auf jeden Fall in Parameter umändern!
Einfach niemals SQL Strings von Hand zusammen bauen, sondern immer Parameter verwenden.
Immer.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
cmd.CommandText = @"insert into Aufgabe (Titel, Art) values ('" + txt_titel.Text + "','" + txt_art.Text + "')";
Ich schreibe SQL Befehle immer komplett in Großbuchstaben, ist leichter zu lesen. Wobei dies hier nicht das Problem ist - nur als Hinweis/Tipp.
Die Lösung hat dir Abt ja bereits gegeben.
Natürlich sollte man Befehle nie so zusammensetzen. Wirklich nie.
Aber verstehen warum es hier einen Fehler gibt, sollte man trotzdem auch.
Ja, genau. Ohne 'Art' funktioniert es problemlos... Sobald ich dies jedoch dazu nehmen buggt es. Ich versuche jetzt nochmal die Parameter auszuschreiben und schaue dann ob es funktioniert... Danke auf jeden Fall für die Hilfe, auch wenn ich gerade ein ziemliches Brett vor dem Kopf habe...
Ist halt nur verwirrend, weil es in dem Buch womit ich mir das beibringe bisschen anders steht.
Ich verstehe noch nicht ganz den Übergang aus dem Beispiel zu Access. Ich habe den Befehl jetzt auseinander gebaut. Doch der Fehler liegt an der Deklarierung. Ich habe das mal anders aufgebaut, jedoch verstehe ich jetzt mein Fehler nicht..
namespace Projekt_DB
{
public partial class cmd_add : Form
{
OleDbConnection con = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Mike\source\repos\Projekt_DB\VerwaltungAufgaben_2020.accdb"); // Connection Databse
string Titel;
string Art;
public cmd_add()
{
InitializeComponent();
txt_prio.Items.Add("1");
txt_prio.Items.Add("2");
txt_prio.Items.Add("3"); // Hinzufügen Kombobox
}
public void cmd_speichern_Click(object sender, EventArgs e)
{
try
{
con.Open(); // Verbindung herstellen zur Datenbank
OleDbCommand cmd = new OleDbCommand("INSERT into Aufgabe (Titel, Art)"); // Hinzufügen in Datenbank
cmd.CommandText = ("VALUES (@txt_titel, @txt_art"); //Textbox auslesen
cmd.Parameters.AddWithValue("@txt_titel", Titel); // @ -> Positionsparameter
cmd.Parameters.AddWithValue("@txt_art", Art);
cmd.ExecuteNonQuery();
MessageBox.Show("Auswahl hinzufügen erfolgreich");
con.Close();
this.Close(); //Schließen des zweiten Fensters
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
}
OleDbCommand cmd = new OleDbCommand("INSERT into Aufgabe (Titel, Art)"); // Hinzufügen in Datenbank cmd.CommandText = ("VALUES (@txt_titel, @txt_art"); //Textbox auslesen
Hast Du Dir mal den CommandText im Debugger angeschaut?
Dein SQL Statement wird hier falsch erstellt.
Durch cmd.CommandText = überschreibst du deinen im Konstruktor von OleDbCommand erstellten Text.
Warum machst du das Insert mit Values nicht vollständig im Konstruktor?
Dann brauchst du auch die Zeile mit dem CommandText nicht noch zusätzlich.
Ebenfalls solltest du an der Benennung der Parameter arbeiten.
Ich würde die empfehlen diese immer den entsprechenden Spaltennamen zu geben, damit klarer wird was der Parameter bedeutet und wo er hingehört.
T-Virus
Developer, Developer, Developer, Developer....
99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
Ja, beim debuggen habe ich eben gesehen, dass der Wert 0 weitergeben wird. Also trifft das zu, dass es überschrieben wird. Aber es hieß doch, dass ich keinen SQL - String benutzen soll, sondern Parameter. Wie verknüpfe ich das dann, dass es nicht überschrieben wird ?
Dann werde ich in Zukunft die Parameter umbenennen
In dem Link steht alles drin, was Du beachten musst. und da steht nirgends, dass Du nen Teil vom SQL über den Konstruktor setzt und den anderen über die Eigenschaft.
Das hast selbst erfunden 😉 siehe Hinweis von T-Virus.
Du musst eigentlich nur den Code aus dem Beispiel kopieren und die Parameternamen anpassen.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Habe das ganze wie im Link beschrieben in Db Provider geändert. Immer noch der gleiche Fehler
public partial class cmd_add : Form
{
OleDbConnection con = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Heino\source\repos\Projekt_DB\VAG_AFG.accdb"); // Connection Databse
public string Titel;
public string Art;
public cmd_add()
{
InitializeComponent();
txt_prio.Items.Add("1");
txt_prio.Items.Add("2");
txt_prio.Items.Add("3"); // Hinzufügen Kombobox
}
public void cmd_speichern_Click(object sender, EventArgs e)
{
try
{
con.Open(); // Verbindung herstellen zur Datenbank
StringBuilder sb = new StringBuilder();
sb.AppendLine("INSERT INTO Aufgaben ([Titel], [Art])");
sb.AppendLine("OUTPUT INSERTED.ID");
sb.AppendLine("VALUES (@txt_titel, @txt_art");
OleDbCommand cmd = new OleDbCommand(sb.ToString(), con);
cmd.Parameters.AddWithValue("@Titel", Titel);
cmd.Parameters.AddWithValue("@Art", Art);
cmd.ExecuteNonQuery();
MessageBox.Show("Auswahl hinzufügen erfolgreich");
con.Close();
this.Close(); //Schließen des zweiten Fensters
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
}
Du solltest dir den Beispiel-Code noch mal anschauen. Du hast zuviele "@" und falsche Parameternamen. Du mußt schon in der SQL-Anweisung und bei der Parameter-Zuweisung die gleichen Namen verwenden.
Weeks of programming can save you hours of planning
Ebefalls kannst du dir den StringBuidler sparen.
Wenn du Mehrzeilige Strings schreiben willst, nutzt das @ dafür.
string sql = @"SELECT * FROM Tabelle
WHERE ID=@Blub";
Nachtrag:
Was mich auch stört ist, dass dein MessageBox.Show vor dem Close der Verbindung kommt.
Ebenfalls solltest du das ganze in eine using packen, dann wird die Verbindung auch ohne expliziten Close Aufruf geschlossen.
Die Objekte werden von dir auch nicht disposed, dafür müsstest du ihne das using noch explizit Dispose aufrufen.
Vom Drei-Schichten-Modell will ich noch nicht anfangen, würde es aber der Sorgfalt halber erwähnen.
T-Virus
Developer, Developer, Developer, Developer....
99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
Ich bin mir nicht sicher, was das OUTPUT im SQL Code soll (ich hab aber mit Access auch nichts am Hut); aber im Endeffekt sollte Dein Code am Ende vom Tag einfach so aussehen:
Ganz simpel, wenige Zeilen Code.
public void AddTaskToDatabase(OleDbConnection connection, string taskTitle, int taskArt) // musste raten welcher Datentyp Art sein soll
{
using (OleDbCommand cmd = new OleDbCommand("INSERT INTO Aufgaben ([Titel], [Art]) OUTPUT INSERTED.ID VALUES (@TITLE, @ART)", connection))
{
cmd.Parameters.AddWithValue("@TITLE", taskTitle);
cmd.Parameters.AddWithValue("@ART", taskArt);
cmd.ExecuteNonQuery();
}
}
Hab mit Absicht unterschiedliche Bezeichner an den Stellen gewählt, damit Du den Überblick hast, wo was hin gehört.
Man kann das ingesamt noch besser machen ( [Artikel] Drei-Schichten-Architektur ) aber solltest erst mal verstehen, was der Code macht.
Aber wie gesagt; hätte eigentlich nur den Code aus dem Beispiel übernehmen müssen und die Parameternamen 1:1 ersetzen müssen.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
@Abt
Wie aus dem Bilderbuch 😃
Genau so sollte der Code im Endeffekt aussehen.
Einfach und sauber.
T-Virus
Developer, Developer, Developer, Developer....
99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
Zusätzlich fehlt im VALUES-Teil auch noch eine schließende Klammer.
Ich bin mir nicht sicher, was das OUTPUT im SQL Code soll
Das kommt aus dem Artikel.
Zusätzlich wird dort bei der Parameterzuweisung auf das "@" verzichtet:
cmd.Parameters.AddWithValue("Birthday", birthday);
Ich weiß auch nicht, wie es bei Access richtig ist, damit habe ich glücklicherweise seit längerem nichts mehr zu tun gehabt.
Allgemein würde ich von Acces auch dringend abraten. Es ist ein Office-Programm und keine Datenbank. Es gibt mittlerweile wesentlich bessere und kostenlose Alternativen.
Weeks of programming can save you hours of planning