删除在带有sql批量插入的事务中不起作用

发布于 2024-12-18 06:22:51 字数 1133 浏览 2 评论 0原文

我需要从表中删除一些记录,然后将一些记录插入到同一个表中。这个删除和插入过程应该在事务中。

下面是我所做的。

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

但是,我想由于在插入之前没有执行删除操作,所以我收到重复的键错误。有人可以帮忙吗?

I need to delete some records from table and then insert some records to the same table. This delete and insert process should be in transaction.

Below is what i did.

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

But, i guess as the delete operation is not getting performed before insert, i get duplicate key errors. Can some one help.?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

弥枳 2024-12-25 06:22:51

我尝试了你的示例代码,它似乎对我有用。我在其中一列上创建了一个 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.尝试运行查询“select CONVERT(datetime, 11/23/2011)”,您就会明白我的意思。

I tried your sample code, and it seemed to work for me. I created a PK on one of the columns to make sure a duplicate insert would throw an error. Then I run the code twice -- the first time through it puts in some dummy data (no errors thrown), the second time through it tries to delete the data and then reinsert within the same transaction. From your question, I was hoping to get an exception the 2nd time through but it worked. Not sure it matters, but I am running SQL Server 2008 R2 SP1.

Here is the complete test code which I used, perhaps it will help you identify your issue.

First the SQL to create a sample table:

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

And the 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();
                }
            }
        }
    }

}

Update on your question
By the way, you didn't get an error because 11/23/2011 was evaluated as a math expression ('/' is division), resulting in the value 0, which was then implicitly cast to a datetime as 1900/01/01. Try running the query "select CONVERT(datetime, 11/23/2011)" and you will see what I mean.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文