Удалить не работает в транзакции с массовой вставкой SQL - PullRequest
4 голосов
/ 27 ноября 2011

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

Вот что я сделал.

 using (SqlConnection sqlConn = new SqlConnection(connectionString))
        {
            sqlConn.Open();
            using (SqlTransaction sqlTran = sqlConn.BeginTransaction())
            {
                string deleteQuery = "delete from dbo.MyTable where Col1 =" + colValue;
                SqlCommand sqlComm = new SqlCommand(deleteQuery, sqlConn,sqlTran);
                sqlComm.ExecuteNonQuery();
                using (SqlBulkCopy sqlcopy = new SqlBulkCopy(sqlConn, SqlBulkCopyOptions.Default, sqlTran))
                {
                    sqlcopy.BatchSize = 10;
                    sqlcopy.DestinationTableName = "MyTable";
                    try
                    {
                        sqlcopy.WriteToServer(dsDataSet.Tables[0]);
                        sqlTran.Commit();
                    }
                    catch (Exception ex)
                    {
                        sqlTran.Rollback();
                    }
                }
            }
        }

Но, я думаю, поскольку операция удаления не выполняется перед вставкой, я получаю дубликат ключаошибки.Может ли кто-нибудь помочь .?

1 Ответ

6 голосов
/ 27 ноября 2011

Я попробовал ваш пример кода, и мне показалось, что он работает.Я создал PK в одном из столбцов, чтобы дубликат вставки выдавал ошибку.Затем я запускаю код дважды - в первый раз через него вводятся некоторые фиктивные данные (без ошибок), во второй раз он пытается удалить данные и затем повторно вставить в ту же транзакцию.От твоего вопроса я надеялся получить исключение во второй раз, но это сработало.Не уверен, что это имеет значение, но я использую SQL Server 2008 R2 SP1.

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

Сначала SQL длясоздайте пример таблицы:

CREATE TABLE [dbo].[MyTable](
    [Col1] [nvarchar](20) NOT NULL,
    [Col2] [nvarchar](20) NULL,
    [Col3] [nvarchar](30) NULL,
    CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED 
    (
        [Col1] ASC
    )
)

и C #:

public static void Main()
{
    DataTable t = new DataTable();
    t.Columns.Add(new DataColumn("Col1"));
    t.Columns.Add(new DataColumn("Col2"));
    t.Columns.Add(new DataColumn("Col3"));
    for (int i = 0; i < 5; i++)
    {
        var r1 = t.NewRow();
        r1["Col1"] = "1" + i.ToString();
        r1["Col2"] = "2" + i.ToString();
        r1["Col3"] = "3" + i.ToString();
        t.Rows.Add(r1);
    }
    t.AcceptChanges();
    var connectionString = new SqlConnectionStringBuilder();
    connectionString.DataSource = "localhost";
    connectionString.InitialCatalog = "testdb";
    connectionString.IntegratedSecurity = true;

    using (SqlConnection sqlConn = new SqlConnection(connectionString.ToString()))
    {
        sqlConn.Open();
        using (SqlTransaction sqlTran = sqlConn.BeginTransaction())
        {
            string deleteQuery = "delete from MyTable"; // just delete them all
            SqlCommand sqlComm = new SqlCommand(deleteQuery, sqlConn, sqlTran);
            sqlComm.ExecuteNonQuery();
            using (SqlBulkCopy sqlcopy = new SqlBulkCopy(sqlConn, SqlBulkCopyOptions.Default, sqlTran))
            {
                sqlcopy.BatchSize = 10;
                sqlcopy.DestinationTableName = "MyTable"; 
                try
                {
                    sqlcopy.WriteToServer(t);
                    sqlTran.Commit();
                }
                catch (Exception ex)
                {
                    sqlTran.Rollback();
                }
            }
        }
    }

}

Обновите свой вопрос Кстати, вы не получили ошибку, потому что 11/ 23/2011 было оценено как математическое выражение ('/' - это деление), в результате чего было получено значение 0, которое затем было неявно приведено к дате и времени как 1900/01/01.Попробуйте выполнить запрос «выберите CONVERT (дата / время, 23.11.2011)», и вы поймете, что я имею в виду.

...