1

ストアドプロシージャから挿入または更新されたIDを取得しようとしていますが、2つの異なる方法を試しました

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

                }
            }
  1. 更新の場合==>xは正しい
  2. 削除の場合==>xはnullです

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

ExecuteNonQuery()とともにRETURNまたはOUTPUTパラメーターを使用することを検討してください。これにより、変数に値が自動的に入力されます。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- net.aspx

于 2013-03-04T22:31:51.203 に答える
0

この場合、出力値が取得されない理由は、出力値を返すのではなく、選択しているためです。プロシージャを変更したくない場合は、最初の結果セットから取得できますが、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 に答える