Вставьте данные в Sql Compact

1

У меня есть Handheld-устройство, которое подключается к базе данных Sql Server, считывает данные сервера Sql и получает его в базе данных SQL Compact, расположенной на устройстве. Это мой код:

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;
    }
}

Все это прекрасно работает, но проблема в том, что все это работает очень медленно. У меня 20 000 строк, которые необходимо вставить в базу данных SQL compact.

Есть ли способ ускорить вставку?

Благодарю.

Теги:
sql-server
compact-framework
windows-mobile

4 ответа

1

Помимо очевидного плохого использования соединения для каждого вызова, вы можете значительно улучшить ситуацию, также полностью устранив процессор запросов. Это означает, что вы не используете SQL. Вместо этого откройте таблицу назначения TableDirect и SqlCeResultset. Итерация по исходным данным (DataTable - плохая идея, но это совершенно другая вещь) и используйте серию CreateRecord, SetValues и Insert.

Хороший пример можно найти здесь (хотя, опять же, я бы использовал SetValues для установки всей строки, а не каждого отдельного поля).

0

Поместите все данные в DataTable а затем используйте SqlCeDataAdapter для сохранения всех данных с помощью одного вызова Update. Возможно, вам придется играть с UpdateBatchSize чтобы получить максимальную производительность.

Глядя более внимательно, я вижу, что у вас уже есть DataTable. Поэтому циклы через него сами по себе смехотворны. Просто отметьте, что, как и у вас, RowState каждого DataRow будет Unchanged, поэтому они не будут вставлены. Я думаю, что вы можете вызвать DataTable.Load таким образом, чтобы все значения RowState оставались как Added но если нет, то вместо этого используйте SqlDataAdapter, установите значение AcceptChangesDuringFill false и вызовите Fill.

0

Повторно используйте свое соединение и не создавайте новое соединение для каждого оператора INSERT.

Вместо того, чтобы передавать строку соединения в ваш метод SqlCE_WriteData_bit, создайте соединение один раз в методе InsertData и передайте объект соединения в SqlCE_WriteData_bit.

0

Есть ли способ ускорить вставку?

Да, но это, вероятно, не будет "приемлемо достаточно быстро", когда мы говорим о вставке 20 тыс. Строк.

Проблема, которую я вижу, заключается в том, что вы открываете соединение для каждой строки, которую вы SqlServer_GetData_dt из SqlServer_GetData_dt, то есть вы открываете соединение для вставки данных в 20 000 раз... открытие соединения - дорогостоящая транзакция. Вы должны построить весь запрос, используя объект StringBuilder а затем выполнить все инструкции insert в одной партии.

Это принесет некоторую выгоду в производительности, но не ожидайте, что она решит вашу проблему. Вставка строк 20k все равно займет некоторое время, особенно если индексы необходимо перестроить. Мое предложение состоит в том, что вы должны тщательно анализировать свои требования и быть немного умнее о том, как вы к нему подходите. Возможные варианты:

  • свяжите предварительно заполненную базу данных, если это возможно, чтобы ваше приложение не должно было страдать от сбоев в производительности процесса обработки населения
  • если нет, запустите процесс insert в фоновом режиме и получите доступ к данным только при завершении предварительного заполнения

Ещё вопросы

Сообщество Overcoder
Наверх
Меню