Laden...

Problem bei Insert von vielen Daten in SQLite DB

Erstellt von simon89 vor 14 Jahren Letzter Beitrag vor 14 Jahren 1.490 Views
S
simon89 Themenstarter:in
32 Beiträge seit 2010
vor 14 Jahren
Problem bei Insert von vielen Daten in SQLite DB

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.");

                }
            }
        }
    }

88 Beiträge seit 2007
vor 14 Jahren

Wenn mich nicht alles täuscht, dann fehlt dir dein SQL-Stament.
"Insert Into" oder "Update"

P
63 Beiträge seit 2005
vor 14 Jahren

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

S
simon89 Themenstarter:in
32 Beiträge seit 2010
vor 14 Jahren

Ä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 😃

88 Beiträge seit 2007
vor 14 Jahren

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

J
3.331 Beiträge seit 2006
vor 14 Jahren

... 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

S
simon89 Themenstarter:in
32 Beiträge seit 2010
vor 14 Jahren

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?

J
3.331 Beiträge seit 2006
vor 14 Jahren

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

S
simon89 Themenstarter:in
32 Beiträge seit 2010
vor 14 Jahren

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)

F
10.010 Beiträge seit 2004
vor 14 Jahren

Und warum so umständlich?

Du kannst auch per OleDB eine Excel Tabelle in ein DataSet lesen.

X
1.177 Beiträge seit 2006
vor 14 Jahren

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.

F
10.010 Beiträge seit 2004
vor 14 Jahren

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.

S
simon89 Themenstarter:in
32 Beiträge seit 2010
vor 14 Jahren

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

F
10.010 Beiträge seit 2004
vor 14 Jahren

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.

S
simon89 Themenstarter:in
32 Beiträge seit 2010
vor 14 Jahren

Ok danke

👍