[英]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
。
由於你必須已經發送它,它已經在@Id
t-sql變量中,這是一個輸出變量,因此可以在客戶端ado.net代碼中訪問它
我喜歡以下模式
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.