1

我正在尝试从存储过程中获取插入或更新的 id,我尝试了 2 种不同的方法

If exists(select ....)出于性能原因,我不允许使用

1-使用输出

    @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();

                }
            }
  1. 如果更新 ==>x是正确的
  2. 如果删除 ==>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;

                }
            }
  1. 如果更新 ==>x为 -1
  2. 如果删除 ==>x是正确的

我怎样才能解决这个问题?我喜欢第一个选项,因为我不需要将输出参​​数传递给存储过程

4

2 回答 2

0

考虑将 RETURN 或 OUTPUT 参数与 ExecuteNonQuery() 一起使用,它会自动将值填充到变量中。不需要 ExecuteScalar()。

http://blogs.msdn.com/b/spike/archive/2009/05/07/a-simple-example-on-how-to-get-return-and-out-parameter-values-using-ado-网络.aspx

于 2013-03-04T22:31:51.203 回答
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);
    }
}

像这样的东西会快得多。即使您认为影响可能很小,也请考虑此类事情。

于 2013-03-04T23:12:13.780 回答