簡體   English   中英

C#SQL存儲過程 - 返回ID

[英]C# SQL stored procedure - returning ID

我有以下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?

干杯,

約翰

只需檢查行是否已經存在,而不是讓@@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

您將設置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 ,因為如果引發異常,則會在SqlTransaction對象的Dispose期間發出Rollback

  1. 你不需要它,你發送它...
  2. 由於你必須已經發送它,它已經在@Id t-sql變量中,這是一個輸出變量,因此可以在客戶端ado.net代碼中訪問它

  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 

然后在客戶端代碼中,您將獲得單行,單列結果集(ADO.Net表),其中包含id值,在所有情況下。

您應該檢查記錄是否存在:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM