SQLite,将DataSet/DataTable复制到数据库文件

5
我已经用另一个数据库文件创建了一个表,并用它填充了一个DataSet。我想将这个DataTable保存到一个新创建的SQLite数据库文件中,但是该表并不在要复制的数据库文件中。请问如何实现呢?如果可以的话,我希望避免使用循环。以下是最佳答案:虽然它包含循环,但可以在2-3秒内写入100,000条记录。
using (DbTransaction dbTrans = kaupykliuduomConn.BeginTransaction())
{
  downloadas.Visible = true; //my progressbar
  downloadas.Maximum = dataSet1.Tables["duomenys"].Rows.Count;

  using (DbCommand cmd = kaupykliuduomConn.CreateCommand())
  {
    cmd.CommandText = "INSERT INTO duomenys(Barkodas, Preke, kiekis) VALUES(?,?,?)";
    DbParameter Field1 = cmd.CreateParameter();
    DbParameter Field2 = cmd.CreateParameter();
    DbParameter Field3 = cmd.CreateParameter();
    cmd.Parameters.Add(Field1);
    cmd.Parameters.Add(Field2);
    cmd.Parameters.Add(Field3);

    while (n != dataSet1.Tables["duomenys"].Rows.Count)
    {
      Field1.Value = dataSet1.Tables["duomenys"].Rows[n]["Barkodas"].ToString();
      Field2.Value = dataSet1.Tables["duomenys"].Rows[n]["Preke"].ToString();
      Field3.Value = dataSet1.Tables["duomenys"].Rows[n]["kiekis"].ToString();
      downloadas.Value = n;
      n++;
      cmd.ExecuteNonQuery();
    }
  }
  dbTrans.Commit();
}

在这种情况下,dataSet1.Tables["duomenys"]已经填充了我需要传输到另一个数据库的所有数据。我也使用循环来填充数据集。
2个回答

9
  • When you load the DataTable from the source database, set the AcceptChangesDuringFill property of the data adapter to false, so that loaded records are kept in the Added state (assuming that the source database is SQL Server)

    var sqlAdapter = new SqlDataAdapter("SELECT * FROM the_table", sqlConnection);
    DataTable table = new DataTable();
    sqlAdapter.AcceptChangesDuringFill = false;
    sqlAdapter.Fill(table);
    
  • Create the table in the SQLite database, by executing the CREATE TABLE statement directly with SQLiteCommand.ExecuteNonQuery

  • Create a new DataAdapter for the SQLite database connection, and use it to Update the db:

    var sqliteAdapter = new SQLiteDataAdapter("SELECT * FROM the_table", sqliteConnection);
    var cmdBuilder = new SQLiteCommandBuilder(sqliteAdapter);
    sqliteAdapter.Update(table);
    

如果源表和目标表具有相同的列名称和兼容类型,则应该可以正常工作...


谢谢,看起来它正在工作...但是非常非常非常慢...将32,000条记录复制到数据库花费了3-4分钟。而且它只有3列...奇怪为什么这么慢? - Tommix
1
尝试在事务中执行更新操作;如果没有显式事务,SQLite会为每个插入隐式创建一个事务,这对于大量插入非常慢。此外,32k条记录相当大,也许您应该尝试分批处理。 - Thomas Levesque
我曾经遇到过类似的性能问题,添加事务解决了我的问题! - Jooeun Lee
由于SqlDataAdapter和SQLiteAdapter实现了IDisposable接口,我认为最好在这两个对象上使用“using”关键字,你同意吗? - Jean-Daniel Gasser
@Jean-DanielGasser 是的 - Thomas Levesque
@ThomasLevesque:非常感谢您提供的解决方案,唯一的问题是DateTime列向SQLite的转换,它只接受INTEGER或TEXT类型的日期。您有什么想法来管理包含DateTime值的列与整数(ticks)之间的转换吗? - Jean-Daniel Gasser

7

使用传统方式将SQL数据导入到SQLite需要很长的时间。当您想导入数百万条数据时,这将花费很多时间。因此,最简单、最快捷的方法是从SQL数据库中获取数据,在DataTable中填充所有行,然后将这些行插入到SQLite数据库中。

public bool ImportDataToSQLiteDatabase(string Proc, string SQLiteDatabase, params object[] obj)
    {
        DataTable result = null;
        SqlConnection conn = null;
        SqlCommand cmd = null;
        try
        {
            result = new DataTable();
            using (conn = new SqlConnection(ConStr))
            {
                using (cmd = CreateCommand(Proc, CommandType.StoredProcedure, obj))
                {
                    cmd.Connection = conn;
                    conn.Open();
                    result.Load(cmd.ExecuteReader());
                }
            }

            using (SQLiteConnection con = new SQLiteConnection(string.Format("Data Source={0};Version=3;New=False;Compress=True;Max Pool Size=100;", SQLiteDatabase)))
            {
                con.Open();
                using (SQLiteTransaction transaction = con.BeginTransaction())
                {
                    foreach (DataRow row in result.Rows)
                    {
                        using (SQLiteCommand sqlitecommand = new SQLiteCommand("insert into table(fh,ch,mt,pn) values ('" + Convert.ToString(row[0]) + "','" + Convert.ToString(row[1]) + "','"
                                                                                                                              + Convert.ToString(row[2]) + "','" + Convert.ToString(row[3]) + "')", con))
                        {
                            sqlitecommand.ExecuteNonQuery();
                        }
                    }
                    transaction.Commit();
                    new General().WriteApplicationLog("Data successfully imported.");
                    return true;
                }
            }
        }
        catch (Exception ex)
        {
            result = null;
            return false;
        }
        finally
        {
            if (conn.State == ConnectionState.Open)
                conn.Close();
        }
    }

相较于之前提供的答案,这将需要很少的时间。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接