verwendetes Datenbanksystem: OLEDB.4.0
Hallo,
ich mal wieder mit einer DB. Frage.
Und zwar erstelle ich einträge in einer Access Datenbank jedoch brauche ich um den weiteren fehlerfreien Verlauf des Programms zu gewährleisten gleich nach dem Insert die ID des eingefügten Datensatzes.
Wie mache ich das am sinnvollsten?
Meine 1. Idee war das ich ein zusätzliches Feld in der Tabelle anlege welches direkt nach dem insert den wert 1 hat und nach der ID abfrage über eben genau dieses neue feld, mach ich ein Update und ändere den wert auf 0.
Das ist meiner Meinung nach keine schöne Lösung. Weiß jemand eine bessere?
lg
Halllo Lo3ty,
so einfach geht das nicht.
Die von dir genannte Lösung wurde zwar funktoinieren ist aber alles andere als eine sichere und saubere Lösung.
Die wohl beste Lösung ist eine Stored Procedure in der Datenbank anzulegen.
Dann kannst du die Daten mit dieser Prozedur einfügen welche automatisch die ID zurückgibt.
Hier findest du ein Beispiel wie man das implementieren könnte
http://forums.asp.net/t/1405516.aspx
Ich sehe, dass sich mein Beispiel auf MS SQL bezieht und deine Frage auf Access, aber ich gehe mal davon aus dass du auch in Access mit Stored Procedures arbeiten kannst 😃
Gruss
Michael
hehe nein davon solltest du nicht ausgehen ^^
ich versuche jetzt mal meine variante und vl. wenn mir mal langweilig ist taste ich micht an deine ran...
danke aber
lg
Hey,
na gut wenn das Access nicht kann dann könnte es ja evtl folgendes.
Und zwar geht das Ganze auch ohne Prozeduren (nur etwas umständlicher).
Du kannst einfach an jeder Abfrage folgendes anhängen
select scope_identity();
oder
select @@identity;
Wieso verwendest du überhaupt Access? Wirst du dazu gezwungen oder machst du das freiwillig? 😉
Ansonsten kann ich dir nur den Umstieg auf den SQL Server empfehlen, denn dieser ist in der Express version auch gratis.
Grüsse
Michael
nun ja ich muss ganz ehrlich sagen ich hab keine ahnung von Datenbanken in C#... Ich arbeite an einem Programm das offline funktionieren soll und bedarf es bei einer Mysql datenbank nicht immer einem laufenden sql server?
kenne das nur von php. mir schien es einfacher eine access datei im verzeichnis der programm exe mitzuführen und diese zu manipulieren.
lg
Hallo Lo3ty,
dann schau Dir mal den SQL Server Compact an, der eignet sich für Offline Lösungen.
Übrigens : MySQL <> MS SQL.
Grüße Bernd
so nachdem die unsaubere variante nicht geklappt hat versuche ich es nun mit der schicken Variante... leider bislang erfolglos....
private void button1_Click_1(object sender, EventArgs e)
{
Int32 zeilen = 0;
string loca = Application.StartupPath;
OleDbConnection con = new OleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + loca + @"\data.mdb");
string strSQL = "Insert into spells (beschreibung) values (?); SELECT CAST (SCOPE_IDENTITY() AS int)";
OleDbCommand cmd = new OleDbCommand(strSQL, con);
con.Open();
zeilen = (Int32)cmd.ExecuteScalar();
//string strSQL = "SELECT * FROM spells";
// DataSet ds = new DataSet();
int w2 = comboBox2.SelectedIndex;
string w4 = textBox1.Text;
switch (w2)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
cmd.Parameters.AddWithValue("@w1", 0);
treeView1.Nodes[0].Nodes[w2].Nodes.Add("{0}", w4);
treeView1.Nodes[0].Nodes[w2].LastNode.Tag = zeilen;
break;
}
cmd.Parameters.AddWithValue("@w2", w2);
cmd.Parameters.AddWithValue("@w3", w3);
cmd.Parameters.AddWithValue("@w4", w4);
cmd.Parameters.AddWithValue("@w5", w5);
cmd.Parameters.AddWithValue("@w6", w6);
cmd.Parameters.AddWithValue("@w7", w7);
cmd.Parameters.AddWithValue("@w8", w8);
cmd.Parameters.AddWithValue("@w9", w9);
cmd.Parameters.AddWithValue("@w10", w10);
cmd.Parameters.AddWithValue("@w11", w11);
cmd.Parameters.AddWithValue("@w12", w12);
cmd.Parameters.AddWithValue("@w13", w13);
cmd.ExecuteNonQuery();
con.Close();
}
was mach ich nun schon wieder falsch?
Ich erhalte als fehler immer: zeichen nach ende von SQL-anweisung gefunden
lg
Hallo Lo3ty,
an der SQL sieht hinten diese schliessende Klammer komisch aus
Versuche es mal einfach nur mit einem SELECT SCOPE_IDENTITY() nach deiner Abfrage. Casten musst du das AFAIK nicht denn das liefert einen int zurück was eh schon erwartet wird.
Weiters ist mir aufgefallen dass du cmd.ExecuteNonQuery() verwendet hast, welches kein Result zurückgibt. Dieses musst du durch cmd.ExecuteScalar() ersetzen, und der Rückgabewert der Methode müsste dann deine ID sein.
Grüsse
Michael
also so:
string strSQL = "Insert into spells (beschreibung) values (?); SELECT SCOPE_IDENTITY() ";
das Execute habe ich ja schon hier:
zeilen = (Int32)cmd.ExecuteScalar();
da bekomme ich beim debugen aber immer den fehler das ein zeichen nach der sql anweisung gefunden wurde... was wiederum darauf hinweißt das die sql anweisung net simmt... ^^
Ich habe mal gelesen, dass ACCESS wie alle OleDbProvider nur eine Anweisung pro query unterstützen. Mach mal das Semikolonn und alles was danach kommt weg. Dann solltest du keinen Fehler mehr haben.
Möglich wäre eine Transaktion aufzumachen und dann die Scope Identity in einem zweiten Command holen. Was dann wieder die voraussetzung ist, dass Access Tranaktionen unterstützt. Sollte gehen.
MFG
Balaban_S
Wieiviel User greifen denn möglicherweise gleichzeitig auf die DB zu. Wenn du nur im SingleUser arbeitest, brauchst du dir auch keine Gedanke um Transaktionen zu machen. Mein Wissensstand zu Access ist eh folgender:[*Keine Transaktionen *Keine mehrfachen Befehle in einem Command *Keine Stored Procedures *Schwerliche Netzwerkunterstüzung
Also wenns geht, dann steig, wie ja auch schon vorgeschlagen wurde, auf MSSQL Compact um. Dann sind alle Probleme wir von Geisterhand verschwunden. (und nutze dort die SqlConnection anstatt von OleDbConnection)
Edit: Tag vergessen
Keine mehrfachen Befehle in einem Command
......
alle Probleme wir von Geisterhand verschwunden.
......
SqlCe unterstützt nach meinem Wissensstand auch keine mehrfachbefehle.
......
MFG
Balaban_S
SqlCe unterstützt nach meinem Wissensstand auch keine mehrfachbefehle.
Wenn dem so ist, ist die CE vom Befehlssatz her ja nicht identisch mit seinem grossen Bruder. Wäre schade.
Als Alternative kann aber immer noch eine Express Edition installiert werden.
Hier noch ein Link zur MSDN-Seite mit den Unterschieden:
Differences Between SQL Server Compact and SQL Server
EDIT: Fehler meinerseits jetzt habe ich selber nachgelesen, dass Mehrfachquerys möglich sind.
MFG
Balaban_S
okay das würde aber bedeuten das ich einfach am ende meines scriptes eine neue verbindung zu der DB herstellen kann und den letzten datensatz abfragen kann oder?
so hab jetzt über den assistenten eine neue sqlce datenbank erstellt... die liegt jetzt aber in meinen eigenen datein. wie bekomme ich die jetzt in mein Projekt?
und wie soll dann der connection string aussehen? habe gelesen dass bei sqlce der pfad wegfällt... wie soll ich dann aber wissen wo die db liegt? ^^
lg
Hi!
Die einfachste Alternative ist immer die clientseitige PrimKey-Generierung.
Da erzeugt der Client die ID, und kann sie gleich verwenden, und wenner abspeichert, wird die mit in die DB geschrieben.
Iwo habich sogar gelesen, clientseitige Prim-Generierung sei Vorraussetzung für or-mapper. hier: Mit_automatischen_Primaerschluesseln_leben
Bei Multi-User-DBs kann man dann aber keine ints als Primkey verwenden, sondern muß die fetten (und in der DB langsamen) Guids nehmen.
Ist 'ne grundsätzliche DB-Design-Frage, womöglich die erste überhaupt.
Meist spielt Geschwindigkeit und Speicher-Aufwand keine Rolle.
Platten-Speicher ist billig, und der Geschwindigkeits-Flaschenhals liegt in der Kommunikation mittm Server.
Also wenn die Kommunikation 0.9s dauert, die Datenerhebung innerhalb der DB nur 0.1s, dann lohntes nicht, Aufwand zu betreiben, um aus letzterer noch 0.05s herauszuholen.
Hallo zusammen,
muss jetzt doch mal hier schreiben. Finde nicht den Fehler.
Ich bekomme folgende Exception:
System.Data.SqlServerCe.SqlCeException: Fehler beim Analysieren der Abfrage. [ Token line number = 1,Token line offset = 255,Token in error = SELECT ]
string queryStockData = "INSERT INTO "+AccountName+"_StockData (StockSymbol, StockName, StockQuantity,"
+ "ShortLong, IndexListing, Sector, Country, Instrument, StockStatus)"
+ "VALUES (@StockSymbol, @StockName, @StockQuantity, @ShortLong, @IndexListing,"
+ "@Sector, @Country, @Instrument, @StockStatus); "
+ "SELECT (scope_identity() AS int)";
SqlCeConnection conn = new SqlCeConnection("DataSource = 'TradingJournal.sdf'");
conn.Open();
SqlCeCommand cmd_AccountBalance = new SqlCeCommand(queryNewAccountBalance, conn);
SqlCeCommand cmd_StockData = new SqlCeCommand(queryStockData, conn);
cmd_StockData.Parameters.Add("@StockSymbol", SqlDbType.NText).Value = this.txt_stockSymbol.Text;
cmd_StockData.Parameters.Add("@StockName", SqlDbType.NText).Value = this.txt_stockName.Text;
cmd_StockData.Parameters.Add("@StockQuantity", SqlDbType.Int).Value = this.txt_stockQuantity.Text;
cmd_StockData.Parameters.Add("@ShortLong", SqlDbType.NText).Value = longshort;
cmd_StockData.Parameters.Add("@IndexListing", SqlDbType.NText).Value = this.cb_index.Text;
cmd_StockData.Parameters.Add("@Sector", SqlDbType.NText).Value = this.cb_sector.Text;
cmd_StockData.Parameters.Add("@Country", SqlDbType.NText).Value = this.cb_country.Text;
cmd_StockData.Parameters.Add("@Instrument", SqlDbType.NText).Value = this.cb_instrument.Text;
cmd_StockData.Parameters.Add("@StockStatus", SqlDbType.NText).Value = "open";
Int32 newID = (Int32)cmd_StockData.ExecuteScalar();
Wo ist jetzt der Fehler im SELECT ?
Vielen Dank für die Hilfe
tomylee
hi
"SELECT (scope_identity() AS int)";
müsste heissen
+Environment.NewLine
+"SELECT @@IDENTITY;";
Edit: SqlCe kennt kein Scope_identity.
Geht aber vielleicht schon in Richtung [Hinweis] Syntaxfehler selbst lösen (Compilerfehlermeldungen)
MFG
Balaban_S
Danke,
glaub mir das habe ich getan, aber das ist mir nicht über den Weg gelaufen.
Aber Problem ist noch nicht ganz weg.
Feure ich den query direkt im Server Manager, dann funktioniert er. Mach ich es im Code dann kommt wieder der SELECT Fehler.
Teilweise wird gesagt das mehrere statements nicht gehen bei CE 3.5 und andere sagen es geht.
Und auf der anderen Seite müsste er ja auch ein Problem im Manager haben.
Bin gespannt wo diesmal mein Denkfehler ist.
Gruß
Hallo tomylee
Auszug aus Balaban_S's Link:
If you want to run multiple queries simultaneously, you must include a new line character for each statement and a semicolon at the end of each statement.
Ich schätze mal dass du dein Statement in deinem Server Manager durch einen Zeilenumbruch getrennt hast, das ist in deinem zusammengestöpselten Statement nicht der Fall.
Zusätzlich kann man die Ausführung in den Management Tools nicht immer mit der Ausführung im Client vergleichen. So unterstützt das SSMS für SQL Server die Möglichkeit unterschiedliche Batches über "GO" voneinander zu trennen. Dies ist jedoch kein T-SQL Keyword sondern wird von Management Studio verarbeitet indem das Skript (vereinfacht gesagt) über "GO" gesplittet wird und die einzelnen Teile nacheinander an den Server gesendet werden.
Grüße
Flo
Hallo Florian,
wenn ich Balabans post richtig verstehe dann macht man das durch +Environment.NewLine und die ; am statement Ende. Das habe ich aber trotzdem Fehler.
Naja, ich feure nen eigenes query und gut
Danke und Abendgruß
Hallo zusammen
Ist schon richtig so jetzt habe ich denMSDN-Link dazu
The Data Provider for Microsoft SQL Server 2005 Everywhere Edition does not support batched queries
Das Problem liegt bei SqlCeCommand(->Managed Provider) welches keine Stapelabfragen unterstützt. Der Server würde es an sich schon.
Ich wusste es doch.
MFG
Balaban_S