4

CSV ファイルから 83 行をロードしましたが、SQLite データベースを更新しようとすると 0 行になりました...何が間違っているのかわかりません。

プログラムの出力:

Num rows loaded is 83
Num rows updated is 0

ソースコードは次のとおりです。

public void InsertData(String csvFileName, String tableName)
{
    String dir = Path.GetDirectoryName(csvFileName);
    String name = Path.GetFileName(csvFileName);

    using (OleDbConnection conn =
        new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
        dir + @";Extended Properties=""Text;HDR=Yes;FMT=Delimited"""))
    {
        conn.Open();
        using (OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM " + name, conn))
        {
            QuoteDataSet ds = new QuoteDataSet();
            adapter.Fill(ds, tableName);
            Console.WriteLine("Num rows loaded is " + ds.Tags.Rows.Count);
            InsertData(ds, tableName);
        }
    }
}

public void InsertData(QuoteDataSet data, String tableName)
{
    using (SQLiteConnection conn = new SQLiteConnection(_connectionString))
    {

        using (SQLiteDataAdapter sqliteAdapter = new SQLiteDataAdapter("SELECT * FROM " + tableName, conn))
        {
            using (new SQLiteCommandBuilder(sqliteAdapter))
            {
                conn.Open();
                Console.WriteLine("Num rows updated is " + sqliteAdapter.Update(data, tableName));
            }
        }
    }
}

正しい行数を更新しない理由についてのヒントはありますか?

アップデート:

更新を呼び出す前にコマンドを設定しようとしましたが、まだ同じ問題が発生しています...コードは次のとおりです。

sqliteAdapter.InsertCommand = cmndBldr.GetInsertCommand();
Console.WriteLine("Num rows updated is " + sqliteAdapter.Update(data, tableName));

デバッグすると、コマンド テキストは次のようになります。_commandText = "INSERT INTO [Tags] ([tagId], [tagName], [description], [colName], [dataType], [realTime]) VALUES (@param1, @param2, @param3, @param4, @param5, @param6)"

これは、データセットの状態を xml 形式で示すペーストです: http://pastie.org/936882

4

2 に答える 2

2

更新

あなたの解決策を読んだ後、私はそれをキャッチできなかったことを恥ずかしく思います。行を列挙して行状態を追加済みに設定すると機能します。

しかし、adapter.AcceptChangesDuringFill を使用して、よりクリーンな方法を提供しましょう。

    using (OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM " + name, conn))
    {
        // this is the proper way to transfer rows
        adapter.AcceptChangesDuringFill = false;

        QuoteDataSet ds = new QuoteDataSet();
        adapter.Fill(ds, tableName);
        Console.WriteLine("Num rows loaded is " + ds.Tags.Rows.Count);
        InsertData(ds, tableName);
    }

これは 83 行をインポートします。

Program.cs

using System;
using System.Data;
using System.Data.SQLite;

namespace SqliteCsv
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            // fill your dataset
            QuoteDataSet ds = new QuoteDataSet();
            ds.ReadXml("data.xml", XmlReadMode.InferTypedSchema);


            // hack to flag each row as new as per lirik
            // OR just set .AcceptChangesDuringFill=false on adapter
            foreach (DataTable table in ds.Tables)
            {
                foreach (DataRow row in table.Rows)
                {
                    row.SetAdded();
                }
            }

            int insertedRows;
            using (
                SQLiteConnection con =
                    new SQLiteConnection(@"data source=C:\Projects\StackOverflowAnswers\SqliteCsv\SqliteCsv\Quotes.db"))
            {
                con.Open();

                // clear table - you may not want this
                SQLiteCommand cmd = con.CreateCommand();
                cmd.CommandText = "delete from Tags";
                cmd.ExecuteNonQuery();


                using (SQLiteTransaction txn = con.BeginTransaction())
                {
                    using (SQLiteDataAdapter dbAdapter = new SQLiteDataAdapter("select * from Tags", con))
                    {
                        dbAdapter.InsertCommand = new SQLiteCommandBuilder(dbAdapter).GetInsertCommand(true);
                        insertedRows = dbAdapter.Update(ds, "Tags");
                    }
                    txn.Commit();
                }
            }
            Console.WriteLine("Inserted {0} rows", insertedRows);

            Console.WriteLine("Press any key");
            Console.ReadKey();
        }
    }
}

元の回答:

これは、最終的に呼び出される SQLiteDataAdapter ctor のソースです。コマンド ビルダーは使用されないことに注意してください。おそらく SQLiteCommandBuilder を使用して、SQLiteDataAdapter で InserCommand プロパティを明示的に設定する必要がありますか?

public SQLiteDataAdapter(string commandText, SQLiteConnection connection)
{
    this.SelectCommand = new SQLiteCommand(commandText, connection);
}
于 2010-04-26T04:39:05.283 に答える
1

各行を調べて呼び出して状態を変更することで問題を回避できましたSetAdded();...その後、 Update コマンドは魅力的に機能しました。

public void InsertData(QuoteDataSet dataSet, String tableName)
{
    int numRowsUpdated = 0;
    using (SQLiteConnection conn = new SQLiteConnection(_connectionString))
    {
        conn.Open();
        using (SQLiteTransaction transaction = conn.BeginTransaction())
        using (SQLiteDataAdapter sqliteAdapter = new SQLiteDataAdapter("SELECT * FROM " + tableName, conn))
        {
            using (sqliteAdapter.InsertCommand = new SQLiteCommandBuilder(sqliteAdapter).GetInsertCommand())
            {
                var rows = dataSet.Tags.AsEnumerable();
                foreach (var row in rows)
                {
                    row.SetAdded();
                }
                numRowsUpdated = sqliteAdapter.Update(dataSet, tableName);
            }
            transaction.Commit();
        }
    }
    Console.WriteLine("Num rows updated is " + numRowsUpdated);
}

DataSetCSV ファイルからUpdateデータが入力され、データをデータベースに挿入するために呼び出しを試みたときに、行の状態が変化を示さないと仮定します。DataAdapterに変更があることを に通知する必要があります。これは、入力元の CSV ファイルに関して にDataSet変更が加えられていないだけであり、これらがデータベースの新しい行であることを認識していないためです。 DataSetm デ​​ータを入れようとしています。

于 2010-04-28T14:38:56.210 に答える