Можно ли иметь несколько инструкций SQL в свойстве ADO.NET Command.CommandText? - PullRequest
8 голосов
/ 14 июля 2011

Резюме

В настоящее время я пишу приложение, в котором я разместил свои инструкции SQL в параметрах проекта.

В коде я получаю значение моего запроса, который возвращает сам запрос. Скажем, например, что мой SQL-запрос выглядит так:

select col1, col2, col3 from my_table

Кроме того, col1, col2 и col3 взяты из разных таблиц и перенесены как внешний ключ в my_table. Поэтому, когда дело доходит до вставки, мне нужно выполнить несколько операторов INSERT, чтобы получить значения из других таблиц для этих вышеупомянутых столбцов. Скажем так:

BEGIN TRANSACTION

insert into first_table (col_x, col_y) values ('col_x', 'col_y')
insert into second_table (col_z, col_a) values ('col_z', 'col_a')
insert into third_table (col_b, col_c) values ('col_b', 'col_c')

и наконец:

insert into my_table (col1, col2, col3, col_v) values (@col1, @col2, @col3, 'col_v')

COMMIT

Предположим, что эти столбцы col1, col2, col3 являются автоматически целыми числами для таблиц first, second и third.

Вопросы

  1. Могу ли я записать сложный оператор SQL в свойство IDbCommand.CommandText, когда каждая инструкция будет разделена точкой с запятой (;)?

  2. Можно ли включить BEGIN TRANSACTION...COMMIT/ROLLBACK в это свойство CommandText?

  3. Короче, могу ли я написать что-то подобное?

    Using cnx = New SqlConnection(connString)
        Using cmd = cnx.CreateCommand()
            cmd.CommandText = "BEGIN TRANSACTION " _
                      & "insert into first_table (col_x, col_y) values ('col_x', 'col_y');" _ 
                      & "insert into second_table (col_z, col_a) values ('col_z', 'col_a');" _
                      & "insert into third_table (col_b, col_c) values ('col_b', 'col_c');" _
                      & "insert into my_table (col1, col2, col3, col_v) values (@col1, @col2, @col3, 'col_v'); " _
                      & "COMMIT"
            cmd.ExecuterNonQuery()
        End Using
    End Using
    

РЕДАКТИРОВАТЬ # 1

Я должен был упомянуть об этом раньше ... Ответ Мака - это то, что я хотел бы сделать, за исключением того, что я не могу из-за странных политик в ИТ-отделе моего клиента, за исключением того, что я использую их пользовательский компонент, который я скорее избегайте ради простоты. Обратите внимание, что я все равно проголосовал за ответ Мак, поскольку это жизнеспособное решение, несмотря ни на что.

Заранее благодарим за вашу драгоценную помощь и время! Это очень важно для меня!

Ответы [ 2 ]

4 голосов
/ 22 июля 2011

Если вы не можете использовать хранимые процедуры, возможно, этот код может соответствовать вашим требованиям:

SqlConnection cnx = new SqlConnection(connString);
SqlCommand cmd = cnx.CreateCommand();
cnx.Open();
string complexCommand = string.Concat(
"DECLARE @first_table AS TABLE(col1 int IDENTITY, col_x varchar(20), col_y varchar(20))"
, " DECLARE @second_table AS TABLE(col2 int IDENTITY, col_z varchar(20), col_a varchar(20))"
, " DECLARE @third_table AS TABLE(col3 int IDENTITY, col_b varchar(20), col_c varchar(20))"
, " DECLARE @my_table AS TABLE(col1 int, col2 int, col3 int, col_v varchar(20))"
, " DECLARE @col1 int"
, " DECLARE @col2 int"
, " DECLARE @col3 int"
, " BEGIN TRAN"
, " BEGIN TRY"
, "   insert into @first_table (col_x, col_y) values ('col_x', 'col_y')"
, "   SET @col1=@@IDENTITY"
, "   insert into @second_table (col_z, col_a) values ('col_z', 'col_a')"
, "   SET @col2=@@IDENTITY"
, "   insert into @third_table (col_b, col_c) values ('col_b', 'col_c')"
, "   SET @col3=@@IDENTITY"
, "   insert into @my_table(col1, col2, col3, col_v) values (@col1, @col2, @col3, 'col_v')"
, "   COMMIT"
, " END TRY"
, " BEGIN CATCH"
, "   ROLLBACK"
, " END CATCH");

cmd.CommandText = complexCommand;
cmd.ExecuteNonReader();

Я добавил табличные переменные по мере необходимости, чтобы запустить пример кода, очевидно, вы можете использовать ваши постоянные таблицы.

4 голосов
/ 15 июля 2011

Попробуйте использовать транзакции ...

using (SqlConnection cnx = new SqlConnection(connString))

{
    cnx.Open();

    // Start a local transaction.
    SqlTransaction sqlTran = cnx.BeginTransaction();

    // Enlist a command in the current transaction.
    SqlCommand command = cnx.CreateCommand();
    command.Transaction = sqlTran;

    try
    {
        // Execute two separate commands.
        command.CommandText = "insert into first_table (col_x, col_y) values ('col_x', 'col_y')";
        command.ExecuteNonQuery();
        command.CommandText = "insert into second_table (col_z, col_a) values ('col_z', 'col_a')";
        command.ExecuteNonQuery();
        command.CommandText = "insert into third_table (col_b, col_c) values ('col_b', 'col_c')";
        command.ExecuteNonQuery();
        command.CommandText = "insert into my_table (col1, col2, col3, col_v) values (@col1, @col2, @col3, 'col_v')";
        command.ExecuteNonQuery();

        // Commit the transaction.
        sqlTran.Commit();
    }
    catch (Exception ex)
    {
        // Handle the exception if the transaction fails to commit.
        // do something with this (ex.Message);
        try
        {
            // Attempt to roll back the transaction.
            sqlTran.Rollback();
        }
        catch (Exception exRollback)
        {
            // Throws an InvalidOperationException if the cnx 
            // is closed or the transaction has already been rolled 
            // back on the server.
            // do something with this (exRollback.Message);
        }
    }
}
...