简体   繁体   English

将数据插入Sql Compact

[英]Insert data into Sql Compact

I have Handheld device that connect to Sql Server database, read the Sql server data and get it on the SQL Compact database that is located on device. 我有连接到Sql Server数据库的手持设备,读取Sql Server数据并在设备上的SQL Compact数据库上获取它。 This is my code: 这是我的代码:

public void InsertData() // Function insert data into SQL commapct database
{
    dt = new DataTable();
    dt = SqlServer_GetData_dt("Select id_price, price, id_item  from prices", SqlCeConnection); // get data form sql server
    if (dt.Rows.Count > 0)
    {
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            string sql = "";
            sql = "insert into prices" +
                " ( id_prices, price,id_item) values('"
                    + dt.Rows[i]["id_price"].ToString().Trim() + "', '"
                    + dt.Rows[i]["price"].ToString().Trim() + "', '"
                    + dt.Rows[i]["id_item"].ToString().Trim() + "')";

            obj.SqlCE_WriteData_bit(sql, connection.ConnectionString);//insert into sql compact
        }
    }


}

public DataTable SqlServer_GetData_dt(string query, string conn)
{
    try
    {
        DataTable dt = new DataTable();
        string SqlCeConnection = conn;
        SqlConnection sqlConnection = new SqlConnection(SqlCeConnection);
        sqlConnection.Open();
        {

            SqlDataReader darSQLServer;
            SqlCommand cmdCESQLServer = new SqlCommand();
            cmdCESQLServer.Connection = sqlConnection;
            cmdCESQLServer.CommandType = CommandType.Text;
            cmdCESQLServer.CommandText = query;
            darSQLServer = cmdCESQLServer.ExecuteReader();
            dt.Load(darSQLServer);
            sqlConnection.Close();
        }
        return dt;
    }
    catch (Exception ex)
    {

        MessageBox.Show(ex.ToString());
        DataTable dt = new DataTable();
        return dt;

    }
}
public object SqlCE_WriteData_bit(string query, string conn)
{
    try
    {
        string SqlCeConnection = conn;
        SqlCeConnection sqlConnection = new SqlCeConnection(SqlCeConnection);
        if (sqlConnection.State == ConnectionState.Closed)
        {
            sqlConnection.Open();
        }
        SqlCeCommand cmdCESQLServer = new SqlCeCommand();
        cmdCESQLServer.Connection = sqlConnection;
        cmdCESQLServer.CommandType = CommandType.Text;
        cmdCESQLServer.CommandText = query;
        object i = cmdCESQLServer.ExecuteScalar();
        sqlConnection.Close();
        return i;

    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
        return 0;
    }
}

This is all work fine but the problem is that all this work very slow. 一切正常,但问题是所有这些工作都很慢。 I have 20 000 row that's need to be inserted into SQL compact database. 我有2万行需要插入到SQL紧凑数据库中。

Is there any way for faster insert? 有什么办法可以更快地插入吗?

Thanks. 谢谢。

Aside from the obvious poor usage of the Connection for every call, you can greatly improve things by also eliminating the query processor altogether. 除了每个调用对Connection的明显使用不佳之外,还可以通过完全消除查询处理器来极大地改善事情。 That means don't use SQL. 这意味着不要使用SQL。 Instead open the destination table with TableDirect and a SqlCeResultset . 而是使用TableDirectSqlCeResultset打开目标表。 The iterate through the source data (a DataTable is a bad idea, but that's a completely different thing) and use a series of CreateRecord , SetValues and Insert . 遍历源数据(DataTable是一个坏主意,但这是完全不同的事情),并使用一系列CreateRecordSetValuesInsert

A pretty good example can be found here (though again, I'd use SetValues to set the entire row, not each individual field). 可以在这里找到一个很好的示例 (尽管再次,我将使用SetValues设置整个行,而不是每个单独的字段)。

Reuse your connection and don't create a new connection for every INSERT statement. 重用您的连接,不要为每个INSERT语句创建一个新的连接。

Instead of passing a connection string to your SqlCE_WriteData_bit method, create the connection once in the InsertData method, and pass the connection object to SqlCE_WriteData_bit . 而是通过一个连接字符串您的SqlCE_WriteData_bit方法,在建立一次连接InsertData方法,和连接对象传递给SqlCE_WriteData_bit

Put all the data into a DataTable and then use a SqlCeDataAdapter to save all the data with one call to Update . 将所有数据放入DataTable ,然后使用SqlCeDataAdapter调用一次Update来保存所有数据。 You may have to fiddle with the UpdateBatchSize to get the best performance. 您可能必须摆弄UpdateBatchSize以获得最佳性能。

Looking more closely, I see that you already have a DataTable . 仔细观察,我发现您已经有一个DataTable Looping through it yourself is therefore ludicrous. 因此,您自己遍历它是荒谬的。 Just note that, as you have it, the RowState of every DataRow will be Unchanged , so they will not be inserted. 只需注意,正如您所拥有的那样,每个DataRowRowState将保持Unchanged ,因此将不会插入它们。 I think that you can call DataTable.Load such that all RowState values are left as Added but, if not, then use a SqlDataAdapter instead, set AcceptChangesDuringFill to false and call Fill . 我认为您可以调用DataTable.Load ,以使所有RowState值都保留为Added但如果没有,则使用SqlDataAdapter ,将AcceptChangesDuringFill设置为false并调用Fill

Is there any way for faster insert? 有什么办法可以更快地插入吗?

Yes, but it probably won't be "acceptably fast enough" when we're talking about inserting 20k rows. 是的,但是当我们谈论插入20k行时,它可能不会“足够快”。

The problem I can see is that you are opening a connection for every single row you are retrieving from SqlServer_GetData_dt , that is, you open a connection to insert data 20k times...opening a connection is an expensive transaction. 我可以看到的问题是,您正在为从SqlServer_GetData_dt中检索的每一行打开一个连接,也就是说,您打开一个连接以插入数据20k次...打开一个连接是一项昂贵的事务。 You should build the whole query using a StringBuilder object and then execute all the insert statements in one batch. 您应该使用StringBuilder对象构建整个查询,然后一批执行所有insert语句。

This will bring some performance gains but don't expect it to solve you're problem, inserting 20k rows will still take some time, specially if indexes need to be re-built. 这将带来一些性能提升,但不要期望它能解决您的问题,插入20k行仍然需要一些时间,特别是如果需要重建索引时。 My suggestion is that you should thoroughly analyse your requirements and be a bit smarter about how you approach it. 我的建议是,您应该彻底分析您的需求,并且对自己的处理方式要聪明一些。 Options are: 选项有:

  • bundle a pre-populated database if possible so your app doesn't have to suffer the population process performance penalties 如果可能,请捆绑一个预先填充的数据库,这样您的应用就不必遭受填充过程的性能损失了
  • if not, run the insert process in the background and access the data only when the pre-population is finished 如果不是,则在后台运行insert过程,仅在预填充完成后才访问数据

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM