2009-09-11 2 views
1

Я работаю над проектом в VB.net, который принимает большие текстовые файлы, содержащие T-SQL, и выполняет их в локальной базе данных SQL, но я столкнулся с проблемой в отношении ошибки обработки.SQL Server 'Resume Next' Equivalent

Я использую следующие технологии:

  • VB.net
  • Framework 3.5
  • SQL Express 2005

SQL, я пытаюсь выполнить в основном неразветвленной но мое приложение полностью не осознает схему или данные, содержащиеся внутри. Например:

UPDATE mytable SET mycol2='data' WHERE mycol1=1 
INSERT INTO mytable (mycol1, mycol2) VALUES (1,'data') 
UPDATE mytable SET mycol2='data' WHERE mycol1=2 
INSERT INTO mytable (mycol1, mycol2) VALUES (1,'data') 
UPDATE mytable SET mycol2='data' WHERE mycol1=3 

Выше приведен образец рода вещи я совершающие, но эти файлы будут содержать около 10 000 до 20 000 заявлений каждого.

Моя проблема в том, что при использовании sqlCommand.ExecuteNonQuery() я получаю исключение, потому что второй оператор INSERT попадает в ограничение первичного ключа в таблице.

Мне нужно знать, что эта ошибка произошла и зарегистрировать ее, но также обрабатывать любые последующие утверждения. Я попробовал обернуть эти инструкции в блоках TRY/CATCH, но я не могу разработать способ обработки ошибки, а затем продолжить обработку других операторов.

Анализатор запросов, похоже, ведет себя таким образом, но не при использовании sqlCommand.ExecuteNonQuery().

Итак, есть ли эквивалент T-SQL «Resume Next» или каким-либо другим способом, я могу сделать это, не вводя огромное количество обработки строк с моей стороны?

Любая помощь очень ценится.

ответ

1

Фактически ваша партия выполняется до конца, так как нарушения ключа не являются исполняемыми партиями. Если вы запустите тот же SQL-файл из Management Studio, вы увидите, что результат был выполнен, и все сообщения были выполнены, а на панели сообщений есть ошибка для с пометкой. SqlClient из ADO.NEt ведет себя точно так же, но в конце пакета (когда возвращается SqlCommand.ExecuteNonQuery), он анализирует возвращаемые сообщения и выдает исключение. Исключением является одно единственное исключение SqlException, но в коллекции Errors содержится SqlError для каждого произошедшего ключевого нарушения.

К сожалению, нет серебряной пули. В идеале файлы SQL не должны вызывать ошибок. Вы можете выбрать итерацию через SqlErrors исключения и решить, на индивидуальной основе, если ошибка была серьезной или вы можете ее игнорировать, зная, что файлы SQL имеют проблемы с качеством данных. Некоторые ошибки могут быть серьезными и не могут быть проигнорированы. См. Database Engine Error Severities.

Другой вариант заключается в том, чтобы явным образом сказать, что SqlClient не бросать. Если вы установите для свойства FireInfoMessageEventOnUserErrors значение true, оно будет вызывать событие SqlConnection.InfoMessage вместо того, чтобы перетаскивать исключение.

+0

Настройка FireInfoMessageEventOnUserError была невероятно полезна для оптимизации производительности. Вместо того, чтобы обрабатывать 1000+ sqlExceptions, это гораздо более быстрый способ справиться с вещами и именно тем, что я искал! –

1

С риском замедления процесса (путем совершения тысяч поездок на SQL-сервер, чем один), вы можете справиться с этой проблемой, разделив файл на несколько отдельных запросов каждый для INSERT или UPDATE. Затем вы можете поймать каждую отдельную ошибку по мере ее совершения и зарегистрировать ее или решить ее, как того требует ваша бизнес-логика.

+0

Это почти тот вывод, к которому я пришел. Это LOT медленнее, но я могу улучшить его, только выполняя строчную линию, если конкретная партия не работает. –

0

Я не знаю способ поддержать резюме, но одним из способов было бы использовать локальную переменную таблицы, чтобы предотвратить ошибки в первую очередь, например,

Declare @Table table(id int, value varchar(100)) 
UPDATE mytable SET mycol2='data' WHERE mycol1=1 
--Insert values for later usage 
INSERT INTO @Table (id, value) VALUES (1,'data') 
--Insert only if data does not already exist. 
INSERT INTO mytable (mycol1, mycol2) 
Select id, Value from @Table t left join 
mytable t2 on t.id = t2.MyCol1 
where t2.MyCol is null and t.id = 1 

EDIT

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

Declare @Table table(id int, value varchar(100)) 

Declare @Step int 
set @Step = 0 
While (1=1) 
Begin 

    Begin Try 

     if @Step < 1 
     Begin     
       Insert into @Table (id, value) values ('s', 1) 
        Set @Step = @Step + 1 
     End 
     if @Step < 2 
     Begin 
      Insert into @Table values (1, 's') 
        Set @Step = @Step + 1 
     End 
     Break 
    End Try 
    Begin Catch 
     Set @Step = @Step + 1 
    End Catch 

End 
Select * from @Table 
1

SQL Server имеет синтаксис Try/Catch. См:

http://msdn.microsoft.com/en-us/library/ms175976.aspx

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

Не существует эквивалента T-SQL «On Error Resume Next» и благодарит Cthulhu за это.

+0

Спасибо, приятно знать, что я просто ничего не пропустил! –

0

К сожалению, я не думаю, что есть способ заставить SqlCommand продолжать обработку после получения ошибки.

Если вы не уверены, приведет ли какая-либо из команд к ошибке или нет (и при некоторой производительности), вы должны разделить команды в текстовом файле на отдельные SqlCommands ..., которые позволят вам использовать try/catch block и найти оскорбительные утверждения.

... это, конечно, зависит от команд T-SQL в текстовом файле, каждый из которых будет находиться в отдельной строке (или иначе очерчен).

0

Один из методов, который я использую, заключается в использовании try/catch и внутри catch, чтобы вывести событие с информацией об исключении. Затем вызывающий может подключить обработчик событий, чтобы делать все, что угодно, с помощью информации (регистрировать ее, собирать для отчетности в пользовательском интерфейсе, что угодно).

Вы также можете включить технику (используемую во многих инфраструктурных областях .NET, например, события Windows.Forms и проверку XSD) передачи объекта CancelableEventArgs в качестве второго аргумента события с логическим полем, которое обработчик события может установить на указывают, что обработка должна прерываться в конце концов.

Еще одна вещь, к которой я призываю вас, - подготовить ваши ВСТАВКИ и ОБНОВЛЕНИЯ, а затем называть их много раз с меняющимися выражениями.

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