我正在尝试从存储过程中获取插入或更新的ID,我尝试了两种不同的方式
出于性能原因,我不允许使用If exists(select ....)
1-使用OUTPUT
@firstName varchar(30),
@Telephone int
AS
BEGIN transaction
UPDATE [PHONE_BOOK].[dbo].[USER]
SET TELEPHONE= @Telephone
output inserted.USERID
where FIRST_NAME = @firstName
if @@ROWCOUNT = 0
begin
INSERT INTO [PHONE_BOOK].[dbo].[USER]
([FIRST_NAME]
,[TELEPHONE])
output inserted.USERID -- or output SCOPE_IDENTITY()
VALUES
(@firstName
,@Telephone)
end
C#代码
IList<SqlParameter> parameters = new List<SqlParameter>();
parameters.Add(new SqlParameter("@firstName", "Mike"));
parameters.Add(new SqlParameter("@Telephone", 9514256));
using (var sqlConnection = new SqlConnection(Config.ConnString))
{
sqlConnection.Open();
using (SqlCommand command = sqlConnection.CreateCommand())
{
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "[dbo].[INSET_USER]";
command.UpdatedRowSource = UpdateRowSource.None;
foreach (SqlParameter oPar in parameters)
command.Parameters.Add(oPar);
object x = command.ExecuteScalar();
}
}
x
是正确的x
为空2-使用OUTPUT参数
@firstName varchar(30),
@Telephone int,
@userId int output
AS
BEGIN transaction
UPDATE [PHONE_BOOK].[dbo].[USER]
SET TELEPHONE= @Telephone
where FIRST_NAME = @firstName
-- i can't find different way to set @userId than doing a select which is not acceptable
if @@ROWCOUNT = 0
begin
INSERT INTO [PHONE_BOOK].[dbo].[USER]
([FIRST_NAME]
,[TELEPHONE])
VALUES
(@firstName
,@Telephone)
set @userId = SCOPE_IDENTITY()
end
c#代码:
IList<SqlParameter> parameters = new List<SqlParameter>();
parameters.Add(new SqlParameter("@firstName", "Mike"));
parameters.Add(new SqlParameter("@Telephone", 9514256));
using (var sqlConnection = new SqlConnection(Config.ConnString))
{
sqlConnection.Open();
using (SqlCommand command = sqlConnection.CreateCommand())
{
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "[dbo].[INSET_USER]";
command.UpdatedRowSource = UpdateRowSource.None;
foreach (SqlParameter oPar in parameters)
command.Parameters.Add(oPar);
command.Parameters.Add("@userId",0).Direction = ParameterDirection.Output;
command.ExecuteNonQuery();
var x = command.Parameters["@userId"].Value;
}
}
x
为-1 x
是正确的我该如何解决这个问题?我提出第一个选项,因为我不需要将输出参数传递给存储过程
答案 0 :(得分:0)
考虑使用RETURN或OUTPUT参数以及ExecuteNonQuery(),它会自动将值填充到变量中。不需要ExecuteScalar()。
答案 1 :(得分:0)
在这种情况下你没有获得输出值的原因是因为你是*选择它而不是*返回它。如果你不想改变你的proc,你可以从第一个结果集中选择它 - 但是ExecuteScalar会抑制结果集,所以你会想要使用ExecuteReader或类似的东西。但是,有一个标准的模式,你没有遵循它,所以我会发布它只是为了好 - 我敢肯定它已被其他地方覆盖。
标准SP模式 -
create proc UpsertMyTable (
@parameter int
) AS
declare @result int
if exists (select 1 from MyTable where value = @parameter) begin
UPDATE HERE
end else begin
INSERT HERE
end
set @result = SCOPE_IDENTITY()
return @result
然后在你的C#代码中,基本上你的示例中的内容是正确的,除了你完成参数的方式是多余的和性能问题......
using (var sqlConnection = new SqlConnection(Config.ConnString)) {
sqlConnection.Open();
using (SqlCommand command = sqlConnection.CreateCommand()) {
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "[dbo].[PROC_UPSERT_SHARE]";
command.UpdatedRowSource = UpdateRowSource.None;
command.parameters.Add(new SqlParameter("@fullName", "dwfae"));
command.parameters.Add(new SqlParameter("@name", "aze"));
command.parameters.Add(new SqlParameter("@root", "aze"));
command.parameters.Add(new SqlParameter("@creationDate", new DateTime(2000, 10, 10)));
command.parameters.Add(new SqlParameter("@lastAccessDate", new DateTime(1999, 11, 11)));
command.parameters.Add(new SqlParameter("@lastWriteDate", new DateTime(1990,12,12)));
command.parameters.Add(new SqlParameter("@subShareCount", 20));
command.parameters.Add(new SqlParameter("@serverId", "serverx"));
object x = command.ExecuteScalar();
Console.WriteLine(x);
}
}
这样的事情会快得多。即使您认为影响可能很小,也请考虑这类事情。