Исключение повторяющегося значения при вставке в таблицу автоинкрементного PK - PullRequest
0 голосов
/ 07 февраля 2011

Недавно я обнаружил SqlCeException: «При вставке записи в таблицу нельзя вставить дублирующее значение в уникальный индекс» (SqlCE 3.5).

Похоже, оператор INSERT нарушает первичный ключограничение.Однако в соответствующей таблице PK был определен как автоинкрементная идентификация:

[ID] int identity(1,1) NOT NULL,

Исключение не является систематическим: оно происходит время от времени.

В чем может быть причинаиз этого исключения?
Разве identity(1,1) не гарантирует уникальный идентификатор для каждой INSERT, не так ли?
Может ли это быть ошибкой SqlCE?Если да, то как его можно обойти?

Вот трассировка исключения (она явно относится к ограничению PK_ID):

System.Data.SqlServerCe.SqlCeException: A duplicate value cannot be inserted into a unique index. [ Table name = HistoricalData,Constraint name = PK_ID ]
  at System.Data.SqlServerCe.SqlCeCommand.ProcessResults(Int32 hr)
  at System.Data.SqlServerCe.SqlCeCommand.ExecuteCommandText(IntPtr& pCursor, Boolean& isBaseTableCursor)
  at System.Data.SqlServerCe.SqlCeCommand.ExecuteCommand(CommandBehavior behavior, String method, ResultSetOptions options)
  at System.Data.SqlServerCe.SqlCeCommand.ExecuteNonQuery()
  at Invensys.Compact.Persistence.SqlCe.PlantData.SaveHistoricalRecord(HistoricalRecord record)
  at ...

Определение таблицы:

CREATE TABLE [HistoricalData] ( 
[ID] int identity(1,1)  NOT NULL,
[Timestamp] datetime NOT NULL,
[Type] smallint NOT NULL,
[IDLastAll] int,
[IDRef] int NOT NULL,
[BinaryLength] smallint NOT NULL,
[Data00] varbinary(500),
[Data01] varbinary(500),
[Data02] varbinary(500),
[Data03] varbinary(500),
[Data04] varbinary(500),
[Data05] varbinary(500),
[Data06] varbinary(500),
[Data07] varbinary(500),
[Data08] varbinary(500),
[Data09] varbinary(500));


--  Create Primary Key Constraints 
ALTER TABLE [HistoricalData] ADD CONSTRAINT [PK_ID] 
    PRIMARY KEY ([ID]);

--  Create Indexes 
CREATE INDEX [IDX_Type_Timestamp]
ON [HistoricalData] ([Type] ASC, [Timestamp] ASC);

CREATE INDEX [IDX_Timestamp]
ON [HistoricalData] ([Timestamp] ASC);

ВСТАВКА выполняется через SqlCeCommand.Вот код (C #):

 _insertRecordCommand =
     new SqlCeCommand
     {
         Connection = _connection,
         CommandType = CommandType.Text,
         CommandText = HISTORICAL_DATA_INSERT
     };

 _insertRecordCommand.Parameters.Add("@Timestamp", SqlDbType.DateTime);
 _insertRecordCommand.Parameters.Add("@Type", SqlDbType.SmallInt);
 _insertRecordCommand.Parameters.Add("@IDLastAll", SqlDbType.Int);
 _insertRecordCommand.Parameters.Add("@IDRef", SqlDbType.Int);
 _insertRecordCommand.Parameters.Add("@BinaryLength", SqlDbType.Int);

 for (var i = 0; i < DATA_BLOCK_NUMBER; i++)
 {
    _insertRecordCommand.Parameters.Add(DATAPARAMETERNAMES[i], SqlDbType.VarBinary, DATA_BLOCK_SIZE);
 }

 _insertRecordCommand.Prepare();

 // Here the parameters are filled.

 _insertRecordCommand.ExecuteNonQuery();

Я пропустил, как параметры заполняются.Тем не менее, параметр [ID] (первичный ключ) отсутствует.

...