2011-01-10 2 views
4

это мой зрХранимая процедура не возвращает 0

CREATE PROCEDURE DeteleTitle 
(
@TitleID int 
) 
AS 
BEGIN 
IF EXISTS(Select TitleID from Titles WHERE [email protected]) 
BEGIN 
DELETE FROM Titles WHERE [email protected] 
SELECT @TitleID 
END 
ELSE 
BEGIN 
SELECT 0 
END 
END 

метод, где я называю это: -

public Int32 DeleteTitle(Int32 TitleID) 
{ 
try 
{ 
int ds=0; 
SqlParameter[] sqlparam=new SqlParameter[1]; 
sqlparam[0]=(@TitleID,TitleID); 
ds=Convert.ToInt32(SqlHelper.ExecuteScalar(ConfigurationManager.ConnectionStrings["con"].ConnectionString,CommandType.StoredProcedure,"DeleteTitle",sqlparam).Tables[0]); 
return ds; 
} 

catch(Exception ex) 
{ 
return 0; 
} 
} 

Теперь TitleID является внешним ключом во многих таблицах. Если в записи какой-либо таблицы используется TitleID, тогда она выдает это исключение, в котором говорится «Нарушение внешнего ключа n». В моей Хранимой процедуре выше я выбираю нуль в блоке else, если удаление не выполняется. Когда delete IS успешно, он возвращает значение TitleID как 50, 99 или что-то еще. Теперь, что происходит, когда удаление не выполняется, оно не возвращает ноль. Я хотел, чтобы сообщение отображалось на экране, основанное на этом нулевом значении, возвращаемом методом «Удалить сохраненную», но когда оно не вернуло никакого значения (при неудачном удалении), я возвратил нуль в блоке catch моего метода DeleteTitle().

Теперь у меня есть два вопроса: -

  1. Почему Хранимая процедура не возвращает ноль, если удаление не удалось?
  2. Возвращает ноль в блоке catch, как я сделал выше правильного пути? Я не знал, как вы извлекаете номер Exception внешнего ключа и прочее, поэтому я просто вернул нуль в catch catch.
+0

Вы должны, по крайней мере, поймать sqlexception (я считаю, что это правильно, если не искать).В настоящее время вы обнаруживаете всевозможные несвязанные исключения здесь и потенциально игнорируете их. Вы должны действительно улавливать определенные исключения, чтобы любые неожиданные могут перейти к обработчику ошибок на уровне приложений для соответствующей обработки и регистрации и что-то еще. – Chris

ответ

3

В вашей процедуре требуется TRY...CATCH, а не ЕСЛИ ... ELSE.

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

3

Проблема заключается в том, что оператор if не будет выполнять инструкцию ELSE, если она завершилась с исключением. Ваш IF-оператор также выглядит некорректным - не должны ли быть IF EXISTS, [затем удалить запись?] Как это написано сейчас, если запись существует, она НЕ будет удалена.

Продвинутая проблема заключается в том, что считается ошибочной практикой полагаться на исключение (в C#, SQL или на любой другой язык) в качестве метода управления потоком.

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

+0

вы правы .. это ЕСЛИ СУЩЕСТВУЕТ только .. была опечатка ... Я ее исправил. вопрос. Есть ли способ для многих таблиц, которые используют этот TitleID как внешний ключ? Все еще проверять явно во ВСЕХ этих таблицах? Пожалуйста, ответьте ..thnx – Serenity

2

Если Tables - это коллекция таблиц, вам понадобится еще один [0] для первого столбца первой таблицы.

+0

Мне кажется, что эти таблицы на самом деле являются «объектами», возвращаемыми методом Execute Scalar. Я ожидал бы, что он исключит исключение (или, вероятно, не компилируется), потому что не будет свойства или метода, называемого «Таблица» на возвращаемом объекте. Возможно, я ошибаюсь. :) – Chris

2

использовать это:

CREATE PROCEDURE DeteleTitle 
(
@TitleID int 
) 
AS 
BEGIN TRY 
    DELETE FROM Titles WHERE [email protected] 
    SELECT CASE 
       WHEN @@ROWCOUNT>0 THEN @TitleID 
       ELSE 0 --row did not exist 
      END 
END TRY 
BEGIN CATCH 
    SELECT 0 --delete failed 
END CATCH 
go 

Когда несколько таблиц «связаны» с помощью внешних ключей и удалить родительскую строку вы получите сообщение об ошибке, как вы сообщаете, потому что ребенок данные не могут существовать без родителей , Вы можете захотеть просмотреть каскадные удаления или добавить код в эту процедуру для удаления из таблиц, связанных с титрами, с помощью внешних ключей. Добавьте эти удаления до DELETE FROM Titles. выполните следующие действия:

CREATE PROCEDURE DeteleTitle 
(
@TitleID int 
) 
AS 
BEGIN TRY 
    BEGIN TRANSACTION 

    DELETE FROM YourOtherTablesA WHERE [email protected] 
    DELETE FROM YourOtherTablesB WHERE [email protected] 

    DELETE FROM Titles WHERE [email protected] 
    SELECT CASE 
       WHEN @@ROWCOUNT>0 THEN @TitleID 
       ELSE 0 --row did not exist 
      END 
    COMMIT 
END TRY 
BEGIN CATCH 
    IF XACT_STATE()!=0 
    BEGIN 
     ROLLBACK TRANSACTION 
    END 
    SELECT 0 --delete failed 
END CATCH 
go 
0

Вы можете использовать @@ ERROR для результата вывода. @@ ERROR = 0 означает успешную неудачную операцию

CREATE PROCEDURE DeteleTitle 
(
    @TitleID int 
) 
AS 

BEGIN 
    IF EXISTS(Select TitleID from Titles WHERE [email protected]) 
    BEGIN 
     DELETE FROM Titles WHERE [email protected]  
    END 

    Select @@ERROR 

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