Я изменил существующую хранимую процедуру. Первоначально у него был один выходной параметр в хранимой процедуре, и он был настроен следующим образом в коде С#, который его вызывал:

cmd.Parameters.Add("@Var1Param", SqlDbType.BigInt);
if (Var1 == 0)
                cmd.Parameters["@Var1"].Value = DBNull.Value;
            else
                cmd.Parameters["@Var"].Value = Var1;
            cmd.Parameters["@Var1"].Direction = ParameterDirection.InputOutput;
cmd.ExecuteNonQuery();

            // Get Var1
Var1= dataMorph.ToInt64(cmd.Parameters["@Var1"].Value.ToString());

Просто чтобы уточнить, этот параметр был объявлен как ВЫХОД в хранимой процедуре, но как ввод-вывод в коде C#. Это сработало нормально.

Я добавил еще один параметр в ту же хранимую процедуру и хочу получить оба параметра из кода C#. Теперь код C# выглядит следующим образом:

  SqlParameter Var1Param;

             if (VAR1 == 0)
                 Var1Param = new SqlParameter("@Var1", DBNull.Value);
             else
                 Var1Param = new SqlParameter("@Var1",Var1) ;

             Var1Param.Direction = ParameterDirection.InputOutput ;
             cmd.Parameters.Add(Var1Param);

Опять же, этот параметр объявляется как вывод в хранимой процедуре, но ввод-вывод в коде С#. Вот новый параметр. Это объявлено как вывод в хранимой процедуре. Вот код С#.

SqlParameter Var2Param = new SqlParameter("@Var2", 0);
            Var2Param.Direction = ParameterDirection.Output;
            cmd.Parameters.Add(Var2Param);

Как видите, я хочу вывести только второй параметр. Присвоение 0 этому параметру кажется стандартной практикой, несмотря на то, что это только выходная переменная. Я не уверен, нужно ли указывать тип.

Теперь исполнение

            // Execute
            cmd.ExecuteScalar();
            connection.Close();

            // Get DonationID
            Var1 = dataMorph.ToInt64(cmd.Parameters["@Var1"].Value.ToString());

            //Get Supersession Daf ID return param to see if new DAF was created
            Var2 = dataMorph.ToInt64(cmd.Parameters["@Var2"].Value.ToString());

Происходит следующее: оба параметра var1 и vaf2 содержат значение, присвоенное параметру @Var2 в хранимой процедуре. Я читал, что можно использовать любое количество параметров и типов параметров, но похоже, что значение, присвоенное @Var2, перезаписывает значение, которое было передано или присвоено Var1.

Любой совет? Я знаю, что могу обойти это, имея несколько наборов результатов и помещая свои выходные значения во второй набор результатов, но я бы предпочел не иметь дело с кладжами, если мне это не нужно. Я видел много сообщений о странном состоянии параметров после того, как они возвращаются из сохраненных процессов и доступны в С#. Является ли такое поведение ошибкой?


Я укажу, что я использую executenonquery, потому что SP выполняет обновление. sarfeast использует скаляр выполнения. Я предполагаю, что это не должно иметь никакого значения, но я спрошу, есть ли у кого-нибудь идеи о том, почему это происходит. Я изменил код, указав размеры для sqlparameters, и теперь значение для var2 отображается в var1, а var2 равно Null!!!

Любой совет будет принят во внимание.

1
Neil Newton 29 Мар 2011 в 18:57
Код, который вы указали, выглядит достаточно справедливо для меня, вы, безусловно, можете использовать параметры таким образом, чтобы возвращать значения из SQL. Однако вы разместили только половину кода, а другая половина находится в процедуре Строда. Если бы вы могли опубликовать SQL, это помогло бы определить проблему.
 – 
JustABitOfCode
30 Мар 2011 в 14:15

1 ответ

Следующий код работает нормально, так что, возможно, это как-то связано с логикой вашей хранимой процедуры?

CREATE PROCEDURE Outs 
    @var1 INT OUTPUT,
    @var2 INT OUTPUT
AS
BEGIN
    SELECT  @var1 = 1,
            @var2 = 2
END
GO

        var connectionstring = @"server=rickshaw;database=becak;Trusted_Connection=true;";

        using(var conn = new SqlConnection(connectionstring))
        using(var cmd = new SqlCommand("Outs", conn))
        {
            try
            {
                cmd.CommandType = CommandType.StoredProcedure;
                conn.Open();

                cmd.Parameters.Add("@var1", SqlDbType.BigInt);
                cmd.Parameters.Add("@var2", 0);

                cmd.Parameters["@var1"].Value = DBNull.Value;
                cmd.Parameters["@var1"].Direction = ParameterDirection.InputOutput;

                cmd.Parameters["@var2"].Value = 0;
                cmd.Parameters["@var2"].Direction = ParameterDirection.Output;

                cmd.ExecuteScalar();
                conn.Close();

                var var1 = cmd.Parameters["@var1"].Value;
                var var2 = cmd.Parameters["@var2"].Value;

                Console.WriteLine("var1=" + var1);
                Console.WriteLine("var2=" + var2);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        Console.ReadLine();
0
Kofi Sarfo 29 Мар 2011 в 19:30
Я рассматривал это как возможность, и, по иронии судьбы, кто-то на форуме sql, где я разместил этот же вопрос, сказал мне, что это должно быть на форуме C # :-).
 – 
Neil Newton
29 Мар 2011 в 21:32