C#SQL存储过程 - 返回ID

时间:2013-11-21 00:51:06

标签: c# sql-server

我有以下SP:

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

这很好用。如果表中已存在计算机名称,则更新签入时间,否则将创建新记录并返回ID。

如果更新记录,我将如何获取@id?

干杯,

约翰

4 个答案:

答案 0 :(得分:3)

只需检查行是否已经存在,而不是让@@ROWCOUNT告诉您是否需要插入。

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

答案 1 :(得分:1)

您可以设置Output参数。代码可能如下所示:

using (SqlConnection c = new SqlConnection(cString))
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;
}

正如Aaron所说,这是一个非常好的锁定候选者,事务编程也是最好的做法。因此,修改后的代码可能如下所示:

lock (_lockObj)
{
    using (SqlConnection c = new SqlConnection(cString))
    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被定义为private object _lockObj = new Object();字段。

注意:您不必担心此处Rollback,因为如果引发异常,Rollback将在Dispose期间发出} SqlTransaction对象。

答案 2 :(得分:0)

  1. 你不需要它,你发送它......
  2. 由于您必须已将其发送,因此它已经在@Id t-sql变量中,这是一个输出变量,因此可以在客户端ado.net代码中访问

    < / LI>
  3. 我喜欢以下模式

      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
    
  4. 然后在客户端代码中,您将获得单行,单列结果集(ADO.Net表),其中包含id值。

答案 3 :(得分:0)

您应该检查记录是否存在:

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