是否SqlBulkCopy的自动启动一个事务? [英] Does SqlBulkCopy automatically start a transaction?

查看:676
本文介绍了是否SqlBulkCopy的自动启动一个事务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通过 SqlBulkCopy的插入数据,像这样:

 公开无效testBulkInsert(字符串连接,字符串表,DataTable的DT)
{
使用(SqlConnection的CON =新的SqlConnection(连接))
{
con.Open();使用(SqlBulkCopy的bulkCopy =新SqlBulkCopy的(CON))
{
bulkCopy.DestinationTableName =表

;
bulkCopy.WriteToServer(DT);
}
}
}



这会不会自动被包裹在SQL事务,这样如果出现通过DB错误的一半将在相同的状态留,因为它是在批量插入之前开始?或将一半的数据插入?



即。是我有必要明确调用 con.BeginTransaction



或者,如果我称之为使用SqlBulkCopy 的构造函数的字符串,是在一个事务?

 <$ C发生得到它的一个更好的办法$ C>公共无效testBulkInsert(字符串连接,字符串表,DataTable的DT)
{使用
(SqlBulkCopy的bulkCopy =新SqlBulkCopy的(连接))
{
bulkCopy.DestinationTableName =表;
bulkCopy.WriteToServer(DT);
}
}



我找到的docs 的在这个问题上有点不清楚,因为他们最初声明




默认情况下,批量复制操作是一个孤立的
执行的操作。在非事务的方式发生大容量复制操作,
与回滚




但后来状态没有机会




默认情况下,批量复制操作是它自己的事务。当你
要执行一个专门的大容量复制操作,创建SqlBulkCopy的一个新实例
有一个连接字符串,或使用现有的
SqlConnection对象不存在活跃交易。在每个场景中,
批量复制操作创建,然后提交或回滚
的交易。




因此,它是必要做的:

 公共无效testBulkInsert(字符串连接,字符串表,DataTable的DT)
{
按(SqlConnection的CON =新的SqlConnection(连接))
{
con.Open();
使用(TR的SqlTransaction = con.BeginTransaction(IsolationLevel.Serializable))使用(SqlBulkCopy的bulkCopy =新SqlBulkCopy的(CON,SqlBulkCopyOptions.Default,TR))
$ {
{
b $ b bulkCopy.DestinationTableName =表;
bulkCopy.WriteToServer(DT);
}
tr.Commit();
}
}
}


解决方案

没有在这里是 SqlBulkCopy的文档文本的 MSDN




默认情况下,批量复制操作是一个孤立的$ b $执行乙方经营。 大容量复制操作中的非事务的方式出现,
与回滚没有机会。如果您需要回滚所有
或部分批量复制发生错误时,你可以使用
SqlBulkCopy的管理事务
,内执行批量复制操作
。现有的交易,或在
System.Transactions的事务入伍




编辑:
正常阅读文档,从中我给你的链接:




默认情况下,批量复制操作是它自己的事务。当你
要执行一个专门的大容量复制操作,创建SqlBulkCopy的一个新的
实例与连接字符串,或使用结果
现有SqlConnection对象不存在活跃交易。在每个
的情况下,大容量复制操作创建,然后提交或回滚
回退事务。




这为案件的内部批量复制的事务,这是不是在默认

 使用(笔试SqlBulkCopy的bulkCopy =新SqlBulkCopy的(
的connectionString,SqlBulkCopyOptions.KeepIdentity |
SqlBulkCopyOptions.UseInternalTransaction))
{
....
}

SqlBulkCopyOptions.UseInternalTransaction ! 您是明确指定SqlBulkCopy类构造函数UseInternalTransaction选项来显式导致批量复制操作在自己的事务执行,导致大容量复制操作的每批单独transaction.Since不同批次在执行中执行不同的事务,如果大容量复制操作过程中出现错误,当前批次的所有行都会被回滚,但是从前面的批次行将保持在数据库中。






如果您需要,因为发生了错误,或者如果批量复制应作为一个更大过程的一部分执行回滚整个大容量复制操作,可以回滚,可以提供的SqlTransaction对象到SqlBulkCopy的构造。



外部事务的情况下。


$ b $使用(SqlBulkCopy的bulkCopy =新SqlBulkCopy的(
destinationConnection b

 使用(的SqlTransaction事务= 
destinationConnection.BeginTransaction())
{
,SqlBulkCopyOptions.KeepIdentity,
交易))
{
....
}
}






就像我说的乞讨答案是否定的,你应该利用现有的交易或内部批量复制交易。阅读文档文件,该文件是在链接,了解更多信息。



如果你想有你应该使用这两种情况,我写了一个事务。


I am inserting data via SqlBulkCopy like so:

public void testBulkInsert(string connection, string table, DataTable dt)
{
    using (SqlConnection con = new SqlConnection(connection))
    {
        con.Open();

        using (SqlBulkCopy bulkCopy = new SqlBulkCopy(con))
        {
            bulkCopy.DestinationTableName = table;
            bulkCopy.WriteToServer(dt);
        }
    }
}

Will this automatically be wrapped in a SQL transaction so that if something goes wrong half way through the DB will be left in the same state as it was before the bulk insert began? Or will half the data be inserted?

i.e. is it necessary for me to explicitly call con.BeginTransaction

Or if I call SqlBulkCopy's constructor that takes a string, is that a better way of getting it to occur in a transaction?

public void testBulkInsert(string connection, string table, DataTable dt)
{
    using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
    {
        bulkCopy.DestinationTableName = table;
        bulkCopy.WriteToServer(dt);
    }
}

I find the docs a bit unclear on this matter as they initially state that

By default, a bulk copy operation is performed as an isolated operation. The bulk copy operation occurs in a non-transacted way, with no opportunity for rolling it back

but then later state

By default, a bulk copy operation is its own transaction. When you want to perform a dedicated bulk copy operation, create a new instance of SqlBulkCopy with a connection string, or use an existing SqlConnection object without an active transaction. In each scenario, the bulk copy operation creates, and then commits or rolls back the transaction.

So is it necessary to do:

public void testBulkInsert(string connection, string table, DataTable dt)
{
    using (SqlConnection con = new SqlConnection(connection))
    {
        con.Open();
        using (SqlTransaction tr = con.BeginTransaction(IsolationLevel.Serializable))
        {
            using (SqlBulkCopy bulkCopy = new SqlBulkCopy(con, SqlBulkCopyOptions.Default, tr))
            {
                bulkCopy.DestinationTableName = table;
                bulkCopy.WriteToServer(dt);
            }
            tr.Commit();
        }
    }
}

解决方案

No here is text from SqlBulkCopy documentation in msdn

By default, a bulk copy operation is performed as an isolated operation. The bulk copy operation occurs in a non-transacted way, with no opportunity for rolling it back. If you need to roll back all or part of the bulk copy when an error occurs, you can use a SqlBulkCopy-managed transaction, perform the bulk copy operation within an existing transaction, or be enlisted in a System.Transactions Transaction.

EDIT: Read properly the documentation, from the link which I gave you:

By default, a bulk copy operation is its own transaction. When you want to perform a dedicated bulk copy operation, create a new instance of SqlBulkCopy with a connection string, or use an
existing SqlConnection object without an active transaction. In each scenario, the bulk copy operation creates, and then commits or rolls back the transaction.

This is written for the case internal bulk copy transaction, which is not the default !

   using (SqlBulkCopy bulkCopy = new SqlBulkCopy(
                       connectionString, SqlBulkCopyOptions.KeepIdentity |
                       SqlBulkCopyOptions.UseInternalTransaction))
   {
       ....
   }

Look closely in SqlBulkCopyOptions.UseInternalTransaction ! You are explicitly specify the UseInternalTransaction option in the SqlBulkCopy class constructor to explicitly cause a bulk copy operation to execute in its own transaction, causing each batch of the bulk copy operation to execute within a separate transaction.Since different batches are executed in different transactions, if an error occurs during the bulk copy operation, all the rows in the current batch will be rolled back, but rows from previous batches will remain in the database.


If you need to roll back the entire bulk copy operation because an error occurs, or if the bulk copy should execute as part of a larger process that can be rolled back, you can provide a SqlTransaction object to the SqlBulkCopy constructor.

The external transaction case.

            using (SqlTransaction transaction =
                       destinationConnection.BeginTransaction())
            {
                using (SqlBulkCopy bulkCopy = new SqlBulkCopy(
                           destinationConnection, SqlBulkCopyOptions.KeepIdentity,
                           transaction))
                {
                     ....
                }
            }


Like I said in the begging the answer is no, you should use existing transaction or internal bulk copy transaction. Read the documentation file which is in the link, for more information.

If you want to have transaction you should use one of the two cases which I wrote.

这篇关于是否SqlBulkCopy的自动启动一个事务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆