2014-09-16 7 views
0

최근까지 실제로 잘 작동하는 것처럼 보인 데이터 이전 도구가 있습니다.멀티 스레딩 할 때 식별 열에 캔트 삽입

Parallel.Foreach를 사용하여 데이터 행 모음을 실행하고 테이블의 새 레코드에 삽입 할 변수를 계산 한 다음 SQL 문을 실행하여 데이터를 삽입하십시오. I 집계 예외가 그러나 다음

Parallel.ForEach<DataRow>(dataTable.Rows, row => 
{ 
    string reference = row["ref"].ToString(); 
    int version = (int)row["version"]; 

    string insertStatement = "INSERT INTO Item (Reference, Version) VALUES (@reference, @version)"; 

    _database.ExecuteCommand(insertStatement, new SqlServerCeParameter[] 
    { 
     new SqlServerCeParameter("@reference", reference, SqlDbType.NVarChar), 
     new SqlServerCeParameter("@version", version, SqlDbType.Int), 
    }); 
}); 

public void ExecuteCommand(string sql, SqlServerCeParameter[] parameters) 
{ 
    //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 
      if (_connection.State == ConnectionState.Closed) _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(); 
     } 
    } 
} 

는의 내부 예외이다

{"The column cannot contain null values. [ Column name = ID,Table name = Item ]"} 

다음과 같이 테이블의 구조는 다음과

CREATE TABLE Item 
(
    ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY, 
    Reference NVARCHAR(50) NOT NULL, 
    Version INT NOT NULL 
); 

이제 돈 ' ID가 ID 열이므로이 오류를 이해해야합니다.

멀티 스레딩 때문에 동시에 두 ID를 계산할 수 없다는 생각이 들었지 만, 이것은 다중 사용자 환경에서 SqlServerCe가 정상적인 의미를 갖는 것처럼 보이지 않습니다.

+0

멀티 스레딩 세계에 오신 것을 환영합니다! 두 스레드가 둘 다 병렬로 실행 중이기 때문에 두 개의 스레드가 ID : 2 레코드를 삽입하기로 결정할 수 있습니다 ... 하나가 손실됩니다 ... – Belogix

+0

@Belogix가 SQL Server Compact에서 자동으로 처리하지 못합니까 ??? – DavidG

+0

ID 열을 문제가되는 기사로 제공하는 예외 메시지로만 이동합니다. –

답변

1

중요 : SQL CE 개체는 스레드로부터 안전하지 않습니다. 내가 SqlCeConnection의 단일 인스턴스라고 추측하는 각 호출에서 _connection을 사용하고 있습니까?

각 스레드는 여러 스레드에서 공유하지 않고 별도의 연결을 사용하는 것이 좋습니다. 따라서 ExecuteCommand 방법으로 새 ​​SqlCeConnection을 만들고 매번 연결해보세요.

이것은 원하는 속도 향상을 얻지 못할 수도 있지만 예상대로 멀티 스레딩이 작동하는지 확신 할 수 없습니다. 이를 위해서는 여러 코어/프로세서가 필요하며 그 자체로 깊은 주제입니다.

+0

그걸 시도했지만 너무 많은 세션 오류가 발생했습니다 :-( –

+0

물론, 시작 줄에는 "SQL CE 개체는 스레드로부터 안전하지 않습니다"라고 표시됩니다. 스레드를 통해 공유를 시작하자마자 실행하게됩니다. 조만간 문제가 생길 수 있습니다. 수영장을 만들거나 스로틀 링해야하지만 공유하지 않아도됩니다. – Belogix

0

IDENTITY_INSERT가 테이블에 대해 설정되어 있는지 확인하십시오.