Как избежать исключения повторяющихся ключей - PullRequest
0 голосов
/ 17 июня 2010

Я использую TableAdapter для вставки записей в таблицу в цикле.

foreach(....)
{
  ....
  ....
  teamsTableAdapter.Insert(_teamid, _teamname);
  ....
}

Где TeamID - это первичный ключ в таблице, а _teamID вставляет его.На самом деле я извлекаю данные из XML-файла, который содержит уникальный teamId

После первого запуска этого цикла, вставка создает исключение Duplicate Primary Key found Exception.Чтобы справиться с этим, я сделал это

foreach(....)
{
  ....
  ....

  try
  {
     _teamsTableAdapter.Insert(_teamid, _teamname);
  }
  catch (System.Data.SqlClient.SqlException e)
  {
     if (e.Number != 2627)
        MessageBox.Show(e.Message);
  }
  ....
  ....
}

Но использование оператора try catch стоит дорого, как избежать этого исключения.Я работаю в VS2010, и INSERT ... ON DUPLICATE KEY UPDATE не работает.

Я хочу избегать операторов try catch и обрабатывать их без использования операторов try catch.

Ответы [ 3 ]

1 голос
/ 17 июня 2010

Исходя из ваших комментариев к другим ответам, я бы предложил изменить TeamID с первичного ключа (если это возможно) и установить новый столбец Idx в качестве первичного ключа.Затем вы можете установить триггер в вашей БД, который при вставке новой записи с дубликатом TeamID обновит исходную запись и удалит новую.

Если это невозможно, я бы изменил хранимую процедурукоторый вставляет запись, так что вместо простой вставки сначала проверяется дубликат TeamID.Если дублирующего идентификатора нет, запись может быть вставлена, в противном случае будет просто «Выбрать 0».

Пример псевдокода:

Declare @Count int
Set @Count = (Select Count(TeamId) From [Table] where TeamId = @TeamId)

If(@Count > 0)
  Begin
    Select 0
  End
Else
 --Insert Logic Here

Затем ваш метод вставки в коде.вместо ExecuteNonQuery () может быть ExecuteScalar ().Ваш код будет обрабатывать это таким образом

If(_teams.TableAdapter.Insert(_teamId, _teamName) == 0)
  {
    _teams.TableAdapter.Update(_teamId, _teamName)
  }

В качестве альтернативы, если вы просто хотите обработать все это в SQL (так что ваш код C # не должен изменяться), вы можете сделать что-то вроде этого:

Declare @Count int
Set @Count = Select Count(TeamId) from [Table] Where TeamId = @TeamId

If(@Count > 0)
  Begin
    //Update Logic
  End
Else
  Begin
    //Insert Logic
  End

Но, опять же, я бы просто изменил таблицу, если это возможно.

1 голос
/ 17 июня 2010

В ваших данных явно есть дубликаты.Либо вам нужно сначала устранить их, либо использовать какой-либо тип слияния, чтобы выполнить isert, если он новый, или обновить, если не новый.

Чтобы увидеть, какие данные являются причиной проблемы, запустите профилировщик, запустив цикл изВаша заявка и увидеть, какие отчеты действительно отправляются.Это указывает на то, какие записи дублируются.

Если это большой файл, массовая вставка (после очистки дубликатов) будет выполняться быстрее, чем построчная обработка.

1 голос
/ 17 июня 2010

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

Обычно это делается с помощью столбца идентификаторов или чего-то подобного.(Похоже, что вы уже могли иметь это с точки зрения TeamID, и в этом случае вам нужно всего лишь изменить его на первичный ключ в SQL-MS или VS2010).

Редактировать: назначить первичный ключ какстолбец идентификаторов (teamID в вашем примере) с использованием Visual Studio:

Перейдите в обозреватель сервера.Перейдите к соответствующей таблице.Щелкните правой кнопкой мыши «Open Table Definition».Нажмите на столбец первичного ключа.Прокручивайте окно свойств, пока не дойдете до «спецификации личности».Измените это на «да» (вы можете установить инкремент / начальное значение на то, что вы хотите. Обычно 1,1 хорошо).Теперь все, что вам нужно сделать, это вставить имя команды в таблицу, и TeamID будет сгенерирован автоматически.

...