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

SqlCommand cmd = new SqlCommand();

        string s = @"

                declare @one_id int; 

                INSERT INTO tbl_one(o1,o2,o3) VALUES(@o1,@o2,@o3);

                set @one_id=SCOPE_IDENTITY();

                INSERT INTO tbl_two(t1,t2,f3) VALUES(@t1,@t2,@one_id);
                INSERT INTO tbl_two(t1,t2,f3) VALUES(@t3,@t4,@one_id);
                INSERT INTO tbl_two(t1,t2,f3) VALUES(@t5,@t6,@one_id);
                ";

        cmd.CommandText =s;
-1
Mike 9 Фев 2015 в 11:43

3 ответа

Лучший ответ

Наверняка вы знакомы с операторами try catch, поэтому используйте их.

Оберните свои утверждения в BEGIN TRANSACTION и COMMIT, например:

        string s = @"
        BEGIN TRY
            BEGIN TRANSACTION 
                declare @one_id int; 

                INSERT INTO tbl_one(o1,o2,o3) VALUES(@o1,@o2,@o3);

                set @one_id=SCOPE_IDENTITY();

                INSERT INTO tbl_two(t1,t2,f3) VALUES(@t1,@t2,@one_id);
                INSERT INTO tbl_two(t1,t2,f3) VALUES(@t3,@t4,@one_id);
                INSERT INTO tbl_two(t1,t2,f3) VALUES(@t5,@t6,@one_id);
            COMMIT
        END TRY
        BEGIN CATCH
            IF @@TRANCOUNT > 0
                ROLLBACK
        END CATCH
        ";

Если одно из ваших операторов завершится неудачно, запустится блок CATCH.

Удачи.

7
Roy Doron 9 Фев 2015 в 09:01

Вы можете запустить транзакцию и управлять ошибками в коде SQL, как предлагает Рой, или сделать это на стороне клиента:

using (SqlConnection cn = CreateConnection())
using (SqlCommand cmd = CreateMyCommand(cn))
{
    cn.Open();
    using (SqlTransaction tx = cn.BeginTransaction())
    {
        cmd.Transaction = tx;
        cmd.ExecuteNonQuery();
        tx.Commit();
    }       
}

Обратите внимание, что блок catch здесь не нужен, потому что, если что-то не удается, транзакция откатывается на tx.Dispose (). Если что-то не удается, tx.commit не вызывается, но всегда вызывается tx.Dispose из-за блока using. Tx.Dispose откатывает транзакцию, если она не была ранее зафиксирована.

2
Jesús López 9 Фев 2015 в 09:41