Hi Leute,
bitte nicht verunglimpfen, ist mein erster Beitrag hier!
Ich benutzt als DBMS SQLite und die System.Data.SQLite Bibliothek
Ich hab ne in nem 2-dimensionalen string array daten liegen (ca. 400 x 25 Daten),
dass in die SQL-DB einfließen soll. Leider funktioniert das nicht so, wie ich mir das vorgestellt habe und würde gerne wissen, ob einer von euch ne idee hätte.
Im Moment pack ich ins SQL einfach nur das wort "test" wie man unten sieht
Wenn ich die ganze Sache ausführe gibts in der Zeile sqliteCmd.ExecuteNonQuery(); nen Fehler:
ArgumentNullException
Value cannot be null.
Parameter name: s
Kann mir evtl. einer helfen?
Hier erstmal der Code:
public void executeInsertOrUpdate(string report, string[,] strArray)
{
using (SQLiteConnection sqliteConn = new SQLiteConnection("Data Source=" + filesource + ";Version=3;Compress=True;UTF8Encoding=True;"))
{
using (SQLiteCommand sqliteCmd = sqliteConn.CreateCommand())
{
//open connection
sqliteConn.Open();
Stopwatch watch = new Stopwatch();
sqliteCmd.Transaction = sqliteConn.BeginTransaction();
watch.Start();
DataTable tableInfo = sqliteConn.GetSchema("Columns", new string[] { null, null, report });
int i = 0;
foreach (DataRow column in tableInfo.Rows)
{
i++;
object[] test = column.ItemArray;
sqliteCmd.Parameters.Add(sqliteCmd.CreateParameter());
}
//insert new data
for (int j = 0; j < 400; j++)
{
for (int k = 0; k < strArray.GetLength(1); k++)
{
if (strArray[j, k] == null)
{
sqliteCmd.Parameters[k].Value = "test";
}
else
{
sqliteCmd.Parameters[k].Value = "test"; // "'" + strArray[j, k] + "'";
}
}
sqliteCmd.ExecuteNonQuery();
}
sqliteCmd.Transaction.Commit();
watch.Stop();
MessageBox.Show("Insert von 400 Elementen: " + watch.ElapsedMilliseconds.ToString() + " ms.");
}
}
}
}
Wenn mich nicht alles täuscht, dann fehlt dir dein SQL-Stament.
"Insert Into" oder "Update"
Da fehlt definitiv das SQL Statement. Es zwar schön und sehr lobenswert das du Parameter verwendest, aber ohne SQL Statement geht es nicht.
gruß phlekk
Ähm ja ... Shame on me ... ich hatte es einfach vergessen und mich dann noch gewundert wieso es nicht funktioniert.
Danke vielmals
Das hier fehlte:
sqliteCmd.CommandText = "INSERT INTO xxx (x,x,x,x ....) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
400 * 23 Inserts brauchen 391 ms 😃
In einer Schleife die in einer Schleife läuft.
Man das auch besteimmt direkt in einem Rutsch in die DB schreiben.
Da weiß ich aber grade nicht wie. Denke, dass es dann noch schneller geht.
Dr.Z
... Man das auch besteimmt direkt in einem Rutsch in die DB schreiben.
Da weiß ich aber grade nicht wie.
Das geht eigentlich nur dann, wenn die Daten schon in einer sauberen Struktur vorhanden sind wie einer DataTable. Wenn sie aber aus einem String-Array kommen (igitt, aber wer weiß, wie das entstanden ist), dann ist dieses Vorgehen akzeptabel; die innere Schleife ordnet schließlich das "innere" Array den Spalten-Parametern zu und ist deswegen richtig.
Jürgen
Danke für die Antwort: Ich könnte die Daten auch als DataTable verfügbar machen.
Wie wäre dann ein Insert mit dem obigen Code besser wenn ich mal so fragen darf?
Hallo Simon,
das hängt davon ab, wie die Daten in die DataTable gelangen. Wenn es durch Rows.Add passiert, gilt immer DataRowState.Added - das ist die beste Voraussetzung (notfalls gibt es eine Methode SetAdded o.ä.). Dann kannst du einen DbDataAdapter erstellen, dazu einen **InsertCommand **(entweder automatisch aufgrund eines SelectCommand mit DbCommandBuilder oder manuell, was bei deiner Vorarbeit wahrscheinlich einfacher ist) und dann DbDataAdapter.Update ausführen. Die Schleife mit der Zuordnung der Parameter und Transaction geht dann sozusagen automatisch.
Ein Mini-Beispiel für den InsertCommand ist auch in [Artikelserie] Parameter von SQL Befehlen enthalten.
Gruß Jürgen
Die Daten kommen aus einer Excelfile und würden wie folgt in eine DataTable geschrieben:
DataTable myvalues = (DataTable)range.Cells.Value2;
(Die Variable range ist vom Typ Microsoft.Office.Interop.Excel.Range)
Und warum so umständlich?
Du kannst auch per OleDB eine Excel Tabelle in ein DataSet lesen.
huhu,
Du kannst auch per OleDB eine Excel Tabelle in ein DataSet lesen.
Davon würde ich abraten. Wenn Excel z.B. einen EAN-Code bekommt, wird der als Wissenschaftliche Zahl formatiert. Wenn man dann per Ole-DB drauf zugreift, sagt einem Excel dass es eine Zahl ist und ruiniert bei der Übergabe den EAN. Auch Zahlen im Format "7.5" (engl. 7,5) werden reinterpretiert -> 7. Mai. Wenn es die erste Zahl in der Sheet-Spalte ist, dann wird ein Datentyp Date angenommen (und alle anderen Zahl die nicht als Datum interpretierbar sind werden aus dieser Spalte verworfen) oder umgekehrt, die falsch interpretierten "Datumswerte" werden verworfen (Weil z.B. die erste Zahl eine 7.0 war).
Das sind Infos die ich nur aus Programmteilen von Kollegen (da die resultierenden Fehler auf meinen Schreibtisch kamen) kenne. Wenn jemand dafür eine "einfache" Lösung mit OleDB hat wär ich dankbar. Ich hab jedenfals bis auf weiteres Excel-InterOp vorgegeben. Das funktioniert soweit wenigstens.
😃
Xynratron
Herr, schmeiss Hirn vom Himmel - Autsch!
Die Erfahrung zeigt immer wieder, dass viele Probleme sich in Luft auslösen, wenn man sich den nötigen Abstand bzw. Schlaf gönnt.
Deshalb fragte ich ja.
Manchmal gibt es den einfachen weg nicht.
Nur meist sind es nur normale Daten, und die gehen dann so einfacher.
Wobei ich würde im Professionellen Umfeld dann eher etwas wie
http://www.gemboxsoftware.com/Spreadsheet/Pricelist.htm
oder
https://www.spreadsheetgear.com/downloads/purchase.aspx
Letzteres gibt/gab es übrigens mal kostenlos wenn man sich als 2005 Express Besitzer
Registriert hat.
Ich habe es mit Excel.Interop gemacht und das funktioniert super und daher möchte ich es gar nicht ändern.
Außerdem war dies nicht das Thema, sondern wie man aus dieser DataTable heraus in meinem obigen Code am besten die Daten in eine sqlite Datenbank einfügt.
Gruß Simon
Natürlich ist das auch eine Frage.
Denn wenn Du die Daten per OleDB gelesen hättest, hättest du im DataAdapter
erst einen Parameter setzen müssen.
Und das mit dem Update einer DataTable in eine DB steht in jeder ADO.NET Einleitung.
Das ist mit jedem DataAdapter gleich.