如何在bulkCopy.WriteToServer之后返回结果

时间:2013-10-01 11:12:16

标签: c# sql-server sql-server-2008 sqlbulkcopy

根据接受的答案

更新

bool success = false;
using (var bulkCopy = new SqlBulkCopy(connection)) //using!
{
    connection.Open();

    //explicit isolation level is best-practice
    using (var tran = connection.BeginTransaction(IsolationLevel.ReadCommitted))
    {
        bulkCopy.DestinationTableName = "table";
        bulkCopy.ColumnMappings...

        using (var dataReader = new ObjectDataReader<SomeObject>(paths))
        {            
            bulkCopy.WriteToServer(dataReader);
            success = true;
        }

        tran.Commit(); //commit, will not be called if exception escapes
    }
}
return success;

我使用BulkCopy类进行大插入,它工作正常 执行WriteToServer并将数据保存到数据库后,我不知道所有数据是否已成功保存,因此我可以返回true/false,因为我需要保存全部或全部内容?

    var bulkCopy = new SqlBulkCopy(connection);

    bulkCopy.DestinationTableName = "table";

    bulkCopy.ColumnMappings...

    using (var dataReader = new ObjectDataReader<SomeObject>(paths))
    {
        try
        {
        bulkCopy.WriteToServer(dataReader);
        }
        catch(Exception ex){ ... }    
}

3 个答案:

答案 0 :(得分:4)

如果对WriteToServer的调用没有例外地完成,则所有行都保存在磁盘上。这只是SQL Server DML的标准语义。批量复制没什么特别的。

与所有其他DML一样,SqlBulkCopy也是全有或全无。除非您配置了您没有的批量大小。

using (var bulkCopy = new SqlBulkCopy(connection)) //using!
{
    connection.Open();

    //explicit isolation level is best-practice
    using (var tran = connection.BeginTransaction(IsolationLevel.ReadCommitted))
    {
        bulkCopy.DestinationTableName = "table";
        bulkCopy.ColumnMappings...

        using (var dataReader = new ObjectDataReader<SomeObject>(paths))
        {
            //try
            //{
            bulkCopy.WriteToServer(dataReader, /*here you set some options*/);
            //}
            //catch(Exception ex){ ... } //you need no explicit try-catch here
        }

        tran.Commit(); //commit, will not be called if exception escapes
    }
}

我已经添加了与最佳实践保持一致的示例代码。

答案 1 :(得分:1)

没有直接的方法来确定流程是否成功完成,除了查找/捕获WriteToServer()方法引发的任何异常。

另一种方法可能是检查数据库中的记录数,然后在流程完成后检查记录数 - 不同之处是插入的数量。将此值与要插入的记录数进行比较可以了解失败或成功。但是,如果有其他进程插入/删除记录,这不是万无一失的。

然而,这些技巧与TransactionScope - http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx或类似的东西一起应该达到您的要求。

修改

默认情况下,每个插入操作都作为批处理进行处理;如果操作在特定批次中失败,则该批次将被回滚,而不是在其之前插入任何批次。

但是,如果内部事务应用于批量操作,则任何行中的失败可以回滚整个结果集。例如;

using (SqlBulkCopy bulkCopy =
   new SqlBulkCopy(connectionString, SqlBulkCopyOptions.KeepIdentity
                   | SqlBulkCopyOptions.UseInternalTransaction))
{
   bulkCopy.BatchSize = 10;
   bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns";

   try
   {
      bulkCopy.WriteToServer(reader);
   }
   catch (Exception ex)
   {
      Console.WriteLine(ex.Message);
   }
   finally
   {
      bulkCopy.Close();
   }
}

上述任何操作中的错误都会导致整个操作回滚。有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/tchktcdk.aspx

答案 2 :(得分:0)

从此函数的docs开始,以下代码段表明您应该捕获任何抛出的异常,否则您可以认为操作成功。

using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString))
{
     bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns";
     try
     {
         // Write from the source to the destination.
         bulkCopy.WriteToServer(reader);
     }
     catch (Exception ex)
     {
         Console.WriteLine(ex.Message);
     }
     finally
     {
         // Close the SqlDataReader. The SqlBulkCopy 
         // object is automatically closed at the end 
         // of the using block.
         reader.Close();
     }
}

如果您想要超级确定,请在批量复制完成后对数据库执行查询以检查行是否存在。