2011-01-10 6 views
4

c'est mon spLa procédure stockée ne retourne pas 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 

Méthode où je l'appelle est: -

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; 
} 
} 

maintenant TitleID est une clé étrangère dans de nombreux tableaux. Si l'enregistrement de certains Table utilise TitreID, il déclenche cette exception qui dit «Violation de clé étrangère n truc». Dans ma procédure stockée ci-dessus, je sélectionne zéro dans le bloc else si la suppression échoue. Lorsque la suppression est réussie, elle renvoie la valeur TitleID comme 50, 99 ou autre. Maintenant, ce qui se passe, c'est que lorsque delete n'est pas réussi, il ne retourne pas zéro. Je voulais qu'un message soit affiché sur l'écran en fonction de cette valeur zéro renvoyée par la procédure Delete Stored mais quand il n'a renvoyé aucune valeur (lorsque la suppression a échoué), j'ai renvoyé zéro dans le bloc catch de ma méthode DeleteTitle().

Maintenant, j'ai deux questions: -

  1. Pourquoi la procédure stockée renvoie pas zéro lorsque suppression a échoué?
  2. Renvoie zéro dans le bloc catch comme je l'ai fait au-dessus de la bonne façon? Je ne savais pas comment vous récupérez le numéro d'Exception de la Clé Étrangère et des trucs donc je viens juste de retourner zéro dans le bloc catch.
+0

Vous devriez au minimum attraper une sqlexception (je crois que c'est correct, sinon le chercher).Actuellement vous attrapez toutes sortes d'exceptions sans rapport ici potentiellement et juste en les ignorant. Vous devriez vraiment attraper des exceptions spécifiques afin que les exceptions inattendues puissent surgir jusqu'à un gestionnaire d'erreurs au niveau de l'application pour traiter, journaliser et quoi que ce soit d'autre. – Chris

Répondre

3

Vous souhaitez un TRY...CATCH dans votre procédure, pas un IF ... ELSE.

Si vous y pensez, vous êtes déjà dans la partie IF de votre instruction lorsque le DELETE échoue avec la violation de clé étrangère. Comment votre code pourrait-il sauter dans le bloc ELSE?

3

Le problème est que votre instruction if n'exécutera pas l'instruction ELSE si elle échoue avec une exception. Votre instruction IF semble également incorrecte - ne devrait-elle pas être IF EXISTS, [puis supprimer l'enregistrement?] La façon dont il est écrit maintenant, si l'enregistrement existe, il ne sera pas supprimé.

Le problème étendu est qu'il est considéré comme une mauvaise pratique de s'appuyer sur une exception (en C#, SQL ou tout autre langage) comme méthode de contrôle de flux.

Il est préférable de vérifier explicitement les enregistrements associés en utilisant l'instruction EXISTS pour chaque table associée.

+0

vous avez raison .. c'est SI EXISTE seulement..était une faute de frappe .. Je l'ai corrigé. une question - Que peut-il y avoir de nombreuses tables qui utilisent TitleID comme une clé étrangère? Toujours vérifier explicitement dans TOUTES ces tables? S'il vous plaît answer..thnx – Serenity

2

Si Tables est une collection de tables, vous aurez besoin d'un autre [0] pour la première colonne de la première table.

+0

Il me semble que ce tables est en fait un "objet" tel que renvoyé par la méthode Execute Scalar. Je m'attendrais à ce qu'il lève une exception (ou ne compile probablement pas réellement) là parce qu'il n'y aura pas une propriété ou une méthode appelée "Table" sur l'objet retourné. Je pourrais avoir tort cependant. :) – Chris

2

utiliser ceci:

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 

Lorsque plusieurs tables sont « liées » via les clés étrangères et vous supprimez une ligne de parent, vous obtenez une erreur comme vous déclarez, parce que les données de l'enfant ne peuvent pas exister sans parent . Vous pouvez rechercher des suppressions en cascade ou ajouter du code dans cette procédure pour les supprimer des tables associées aux Titres via des clés étrangères. Ajoutez ces suppressions avant le DELETE FROM Titles. faites-le comme ceci:

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

Vous pouvez utiliser @@ ERROR pour le résultat de sortie. @@ ERROR = 0 signifie réussite d'une autre opération infructueuse

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 
Questions connexes