2014-09-15 3 views
1

У меня есть # приложение C, предназначенный для переноса данных из MS Access в SQL Server Compact 4.0SQL Server Ce 4.0 Ошибка 2700

Существует большое количество данных, и как таковой я, используя большое количество параллельных. Foreach, чтобы просмотреть данные, и в базу данных SQL Server CE имеется большое количество Reads and Writes (но только одно из чтения из базы данных доступа).

Это работает очень хорошо для хорошего получаса и на самом деле база данных заполняются (я могу видеть это от размера файла и проверками после того, как произошла ошибка)

Однако в конечном итоге я получаю Совокупное исключение брошено чье внутреннее исключение:

SQLServerCEException: Слишком много сеансов Открыть, NativeError 27000

Я искал Google и единственное решение, которое я нашел, было явно закрыть все команды s, соединения и адаптеры, когда они закончены, даже если они находятся в операциях использования.

Эти три метода, которые я использую для взаимодействия с базой данных:

/// <summary> 
/// Executes a single INSERT, UPDATE, DELETE or other Sql Command that modifies the schema or data of the database 
/// </summary> 
/// <param name="sql">The command to execute</param> 
/// <param name="parameters">Any parameters in the command</param> 
public void ExecuteCommand(string sql, SqlServerCeParameter[] parameters) 
{ 
    //print debug statements if necessary 
    if (_outputSqlStatementsToFile == true) PrintSqlDebuggingInformation(sql, parameters); 

    //create a new connection using the connection string 
    using (var connection = new SqlCeConnection(_connectionString)) 
    { 
     //create the command that will execute the Sql 
     using (var command = new SqlCeCommand(sql, connection)) 
     { 
      //add any parameters 
      if (parameters != null) command.Parameters.AddRange(parameters.Select(p => p.ParameterBehind).ToArray()); 

      try 
      { 
       //open the connection 
       connection.Open(); 

       //execute the command 
       command.ExecuteNonQuery(); 
      } 
      catch (SqlCeException ex) 
      { 
       //only catch if the native error is the duplicate value exception otherwise throw as normal 
       if (ex.NativeError != 25016) throw; 
      } 
      finally 
      { 
       //explicitly close command 
       command.Dispose(); 
      } 
     } 
     //explicitly close the connection 
     connection.Close(); 
    } 
} 

/// <summary> 
/// Executes a query that returns a single value, for example a COUNT(*) query 
/// </summary> 
/// <typeparam name="T">The type of the value returned by the query, for example COUNT(*) would be an Integer</typeparam> 
/// <param name="sql">The query to execute</param> 
/// <param name="parameters">Any parameters in the query</param> 
/// <returns>A single value cast to type T</returns> 
public T ExecuteQuery<T>(string sql, SqlServerCeParameter[] parameters) 
{ 
    //print debug statements if necessary 
    if (_outputSqlStatementsToFile == true) PrintSqlDebuggingInformation(sql, parameters); 

    //the result 
    T result; 

    //create a new connection using the connection string 
    using (var connection = new SqlCeConnection(_connectionString)) 
    { 
     //create the command that will execute the Sql 
     using (var command = new SqlCeCommand(sql, connection)) 
     { 
      //add any parameters 
      if (parameters != null) command.Parameters.AddRange(parameters.Select(p => p.ParameterBehind).ToArray()); 

       //open the connection 
       connection.Open(); 

       //execute the command and cast the result to the type given to the method 
       result = (T)command.ExecuteScalar(); 

       //explicitly dispose the command 
       command.Dispose(); 
     } 
     connection.Dispose(); 
    } 
    //return the result 
    return result; 
} 

/// <summary> 
/// Executes a query that returns a list of rows in a data table 
/// </summary> 
/// <param name="sql">The query to execute</param> 
/// <param name="parameters">Any parameters in the query</param> 
/// <returns>A data table of rows matching the query</returns> 
public DataTable ExecuteQuery(string sql, SqlServerCeParameter[] parameters) 
{ 
    //print debug statements if necessary 
    if (_outputSqlStatementsToFile == true) PrintSqlDebuggingInformation(sql, parameters); 

    //the returnable data table 
    var table = new DataTable(); 

    //create a new connection using the connection string 
    using (var connection = new SqlCeConnection(_connectionString)) 
    { 
     //create the command that will execute the Sql 
     using (var command = new SqlCeCommand(sql, connection)) 
     { 
      //add any parameters 
      if (parameters != null) command.Parameters.AddRange(parameters.Select(p => p.ParameterBehind).ToArray()); 

      //create an adapter to which will fill the data table that is to be returned 
      using (var adapter = new SqlCeDataAdapter(command)) 
      { 
       //open the connection 
       connection.Open(); 

       //fill the table using the adapter 
       adapter.Fill(table); 

       //explicitly dispose the adapter 
       adapter.Dispose(); 
      } 
      command.Dispose(); 
     } 
     connection.Dispose(); 
    } 
    //return the result 
    return table; 
} 

Эти методы называются бесчисленное количество раз, и это, как правило, на command.ExecuteNonQuery() в первом методе, который возникает ошибка.

Есть ли у кого-нибудь предложения?

ответ

1

Я предлагаю не открыть/закрыть соединение для каждого оператора SQL. Вместо этого открывайте такие числовые соединения, сколько параллельных процессов - по одному для каждого. Открывайте соединения при начале миграции и закрывайте их. Вы можете выпустить множество операторов SQL, используя одно и то же открытое соединение.

В качестве альтернативы вы можете использовать простую реализацию пула соединений, как это: «Creating a custom database connection pool - CodeProject»

Это также повышает эффективность миграции.

+0

вы знаете о пулах соединений в C# это не так много ожидать .. так что вы предлагаете, я бы убедиться, что он приносит пользу потребности Op, если бы это было 'Delphi' я бы сказал, хорошее предложение, но C# обрабатывает подключение пулы по-разному – MethodMan

Смежные вопросы