开发环境
VS2022
net4.5
上位机程序
在 C# .NET Framework 4.5 中,将多个数据同步到本地 SQL Server 数据库表,并实现高性能的 SqlCommand 插入操作,最佳实践是使用 SqlBulkCopy。这是微软提供的专门用于高效批量插入数据的类。
以下是几种不同的实现方式,从最推荐的 SqlBulkCopy 开始:
方法一:使用 SqlBulkCopy (推荐 - 最高性能)
这种方法是处理大量数据插入时最高效的方式。
cs
using System;
using System.Data;
using System.Data.SqlClient; // 注意:.NET Framework 4.5 使用 System.Data.SqlClient
using System.Diagnostics;
public class DataSyncService
{
private readonly string _connectionString;
public DataSyncService(string connectionString)
{
_connectionString = connectionString;
}
/// <summary>
/// 使用 SqlBulkCopy 将数据列表高效地插入到数据库中
/// </summary>
/// <typeparam name="T">数据对象的类型</typeparam>
/// <param name="dataList">要插入的数据列表</param>
/// <param name="tableName">目标数据库表名</param>
public void BulkInsert<T>(IList<T> dataList, string tableName) where T : class
{
if (dataList == null || !dataList.Any()) return;
// 1. 将 List<T> 转换为 DataTable
var dataTable = ConvertToDataTable(dataList);
// 2. 执行批量插入
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
using (var bulkCopy = new SqlBulkCopy(connection))
{
bulkCopy.DestinationTableName = tableName;
// 设置超时时间(可选,默认30秒)
bulkCopy.BulkCopyTimeout = 300; // 5分钟
// 设置批处理大小(可选,默认值为0,表示一次性全部提交)
// 设置一个合理的批次大小可以减少内存占用和网络压力
bulkCopy.BatchSize = 10000;
// 映射列(如果DataTable的列名与数据库表的列名不完全一致,需要手动映射)
// 例如: bulkCopy.ColumnMappings.Add("Name", "DbNameColumn");
// 如果列名完全一致,可以省略这一步。
bulkCopy.WriteToServer(dataTable);
}
}
}
/// <summary>
/// 将任意类型的 List 转换为 DataTable
/// </summary>
private DataTable ConvertToDataTable<T>(IList<T> data) where T : class
{
var properties = TypeDescriptor.GetProperties(typeof(T));
var table = new DataTable();
// 添加列
foreach (PropertyDescriptor prop in properties)
{
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
}
// 添加行
foreach (var item in data)
{
var row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
{
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
}
table.Rows.Add(row);
}
return table;
}
}
// --- 使用示例 ---
class Program
{
static void Main(string[] args)
{
var connectionString = "Server=localhost;Database=TestDB;Trusted_Connection=true;";
var syncService = new DataSyncService(connectionString);
// 假设你的数据模型
var users = new List<User>();
for (int i = 0; i < 100000; i++)
{
users.Add(new User { Id = i, Name = $"User{i}", Email = $"user{i}@example.com" });
}
Console.WriteLine($"开始同步 {users.Count} 条记录...");
var sw = Stopwatch.StartNew();
// 执行批量插入
syncService.BulkInsert(users, "Users");
sw.Stop();
Console.WriteLine($"同步完成,耗时: {sw.ElapsedMilliseconds} ms");
}
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
方法二:使用事务中的参数化 SqlCommand (适用于中等数量数据或复杂逻辑)
如果数据量不是特别大(例如几千到几万条),或者需要在插入过程中执行复杂的业务逻辑判断,可以使用带事务的 SqlCommand。
cs
public class DataSyncServiceWithTransaction
{
private readonly string _connectionString;
public DataSyncServiceWithTransaction(string connectionString)
{
_connectionString = connectionString;
}
/// <summary>
/// 在一个事务中批量执行参数化命令进行插入
/// </summary>
/// <param name="dataList">要插入的数据列表</param>
/// <param name="insertCommandText">INSERT SQL语句</param>
public void InsertInTransaction(List<User> dataList, string insertCommandText)
{
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
using (var transaction = connection.BeginTransaction())
{
try
{
using (var command = new SqlCommand(insertCommandText, connection, transaction))
{
command.Parameters.Add("@Id", SqlDbType.Int);
command.Parameters.Add("@Name", SqlDbType.NVarChar, 255);
command.Parameters.Add("@Email", SqlDbType.NVarChar, 255);
foreach (var user in dataList)
{
command.Parameters["@Id"].Value = user.Id;
command.Parameters["@Name"].Value = user.Name;
command.Parameters["@Email"].Value = user.Email;
command.ExecuteNonQuery();
}
}
transaction.Commit();
Console.WriteLine("所有数据已成功插入!");
}
catch
{
transaction.Rollback();
Console.WriteLine("发生错误,事务已回滚。");
throw;
}
}
}
}
}
对比
| 方法 | 适用场景 | 性能 | 复杂度 |
|---|---|---|---|
| SqlBulkCopy | 大量数据 (>10k+ 行) | 最高 | 低 (需要转换为 DataTable) |
| 事务中的 SqlCommand | 中等数据量或需要逐条处理逻辑 | 较高 | 中 |