Procédure stockée C # SQL – ID de return

J'ai le SP suivant:

ALTER Procedure [dbo].[SP_RegisterComp] @CompName varchar(100) ,@Check_In datetime ,@ID int output As Set NoCount On Update Host Set [Check_In]=@Check_In Where [CompName]=@CompName If @@RowCount=0 Insert into Host values (@CompName, @Check_In) SET @ID=SCOPE_IDENTITY() RETURN @ID 

Cela fonctionne bien. Si un nom d'ordinateur existe déjà dans la table, l'heure d'arrivée est mise à jour, sinon elle crée un nouvel logging et renvoie l'ID.

Comment puis-je get le @id lorsque l'logging est mis à jour?

À votre santé,

John

Vérifiez simplement si la ligne existe déjà au lieu de laisser @@ROWCOUNT vous dire si l'insertion est nécessaire.

 ALTER PROCEDURE [dbo].[SP_RegisterComp] @CompName varchar(100) ,@Check_In datetime ,@ID int output AS SET NOCOUNT ON; SELECT TOP 1 @Id = [IdField] FROM Host WHERE [CompName] = @CompName ORDER BY [Check_In] DESC IF (@Id IS NOT NULL) BEGIN UPDATE Host SET [Check_In]=@Check_In WHERE [IdField] = @Id END ELSE BEGIN INSERT INTO Host VALUES (@CompName, @Check_In) SET @ID=SCOPE_IDENTITY() END RETURN @ID 

Vous devez configurer un paramètre de Output . Le code pourrait ressembler à ceci:

 using (SqlConnection c = new SqlConnection(cSsortingng)) using (SqlCommand cmd = new SqlCommand("SP_RegisterComp", c)) { cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@CompName", compName); cmd.Parameters.AddWithValue("@Check_In", checkIn); var outParm = new SqlParameter("@ID", SqlDbType.Int); outParm.Direction = ParameterDirection.Output; cmd.ExecuteNonQuery(); var val = outParm.Value; } 

Comme Aaron l'a suggéré, c'est un très bon candidat pour le locking, et la programmation transactionnelle est toujours une bonne pratique ici aussi. Ainsi, le code modifié pourrait ressembler à ceci:

 lock (_lockObj) { using (SqlConnection c = new SqlConnection(cSsortingng)) using (SqlTransaction tran = c.BeginTransaction()) using (SqlCommand cmd = new SqlCommand("SP_RegisterComp", c, tran)) { cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@CompName", compName); cmd.Parameters.AddWithValue("@Check_In", checkIn); var outParm = new SqlParameter("@ID", SqlDbType.Int); outParm.Direction = ParameterDirection.Output; cmd.ExecuteNonQuery(); // commit the transaction tran.Commit(); var val = outParm.Value; } } 

_lockObj est défini comme private object _lockObj = new Object(); comme un champ.

Remarque: vous n'avez pas besoin de vous inquiéter de la Rollback ici car si une exception est SqlTransaction la SqlTransaction sera lancée pendant l' SqlTransaction object SqlTransaction .

Vous devriez vérifier si l'logging existe:

 If EXISTS (SELECT * FROM Host WHERE [CompName] = @CompName) BEGIN BEGIN TRAN SELECT @ID=ID FROM Host WITH(UPDLOCK) WHERE Comp_Name = @Comp_Name UPDATE Host SET [Check_In] = @Check_In WHERE [Comp_Name] = @Comp_Name RETURN @ID COMMIT TRAN END ELSE BEGIN Insert into Host values (@CompName, @Check_In) SET @ID=SCOPE_IDENTITY() RETURN @ID END 
  1. Vous n'en avez pas besoin alors, vous l'avez envoyé …
  2. Puisque vous devez l'avoir envoyé, il est déjà dans la @Id t-sql, qui est une variable de sortie donc il est accessible dans le code client ado.net

  3. J'aime le motif suivant

      Alter Procedure [dbo].[SP_RegisterComp] @CompName varchar(100), @Check_In datetime. @ID int = null As Set NoCount On If @Id is null Begin Insert ... SET @ID=SCOPE_IDENTITY() End Else Begin Update ... Where id = @Id End Select @Id id Return 0 

Ensuite, dans le code client, vous obtiendrez un jeu de résultats à une seule ligne et une seule colonne (une table ADO.Net) avec la valeur de l'ID dans tous les cas.