Sch*_*tzE 23 sql-server sqlbulkcopy
我正在使用SQLBulkCopy来移动大量数据.我实现了通知事件,以便每次处理完一定数量的行时通知我,但是当作业完成时,OnSqlRowsCopied事件不会触发.如何在SQLBulkCopy writetoserver完成时获取复制的总行数?
Ben*_*nzi 31
以下hack(使用反射)是一个选项:
/// <summary>
/// Helper class to process the SqlBulkCopy class
/// </summary>
static class SqlBulkCopyHelper
{
static FieldInfo rowsCopiedField = null;
/// <summary>
/// Gets the rows copied from the specified SqlBulkCopy object
/// </summary>
/// <param name="bulkCopy">The bulk copy.</param>
/// <returns></returns>
public static int GetRowsCopied(SqlBulkCopy bulkCopy)
{
if (rowsCopiedField == null)
{
rowsCopiedField = typeof(SqlBulkCopy).GetField("_rowsCopied", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance);
}
return (int)rowsCopiedField.GetValue(bulkCopy);
}
}
Run Code Online (Sandbox Code Playgroud)
然后使用如下类:
int rowsCopied = SqlBulkCopyHelper.GetRowsCopied(bulkCopyObjectInYourCode);
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.
小智 7
为了完整性,我已经实现了扩展方法并包含了命名空间.如果您想要快速解决方案来获取复制的计数,请复制并粘贴此类.注意:当Ignore Duplicates设置为ON时,此计数不考虑实际插入的行数.
namespace System.Data.SqlClient
{
using Reflection;
public static class SqlBulkCopyExtension
{
const String _rowsCopiedFieldName = "_rowsCopied";
static FieldInfo _rowsCopiedField = null;
public static int RowsCopiedCount(this SqlBulkCopy bulkCopy)
{
if (_rowsCopiedField == null) _rowsCopiedField = typeof(SqlBulkCopy).GetField(_rowsCopiedFieldName, BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance);
return (int)_rowsCopiedField.GetValue(bulkCopy);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这就是我所做的 - 这是对该线程中 Rahul Modi 解决方案的轻微修改(基本上它只是将 SqlRowsCopied 事件内联,我认为在这个实例中这比创建新的事件处理程序方法更清晰):
private long InsetData(DataTable dataTable, SqlConnection connection)
{
using (SqlBulkCopy copier = new SqlBulkCopy(connection))
{
var filesInserted = 0L;
connection.Open();
copier.DestinationTableName = "dbo.MyTable";
copier.NotifyAfter = dataTable.Rows.Count;
copier.SqlRowsCopied += (s, e) => filesInserted = e.RowsCopied;
copier.WriteToServer(dataTable);
connection.Close();
return filesInserted;
}
}
Run Code Online (Sandbox Code Playgroud)
通过使用SqlBulkCopy.SqlRowsCopied Event(每次NotifyAfter在处理该属性指定的行数时发生),我们可以在完成时实现SQLBulkCopy行数。
using (SqlBulkCopy s = new SqlBulkCopy(db.Database.Connection as SqlConnection))
{
s.SqlRowsCopied += new SqlRowsCopiedEventHandler(sqlBulk_SqlRowsCopied);
s.BatchSize = csvFileData.Rows.Count;//DataTable
s.NotifyAfter = csvFileData.Rows.Count;
foreach (var column in csvFileData.Columns)
s.ColumnMappings.Add(column.ToString(), column.ToString());
// Set the timeout.
s.BulkCopyTimeout = 60;
s.DestinationTableName = "Employee_Data";
s.WriteToServer(csvFileData);
}
private static void sqlBulk_SqlRowsCopied(object sender, SqlRowsCopiedEventArgs e)
{
long Count = e.RowsCopied;
}
Run Code Online (Sandbox Code Playgroud)