使用SqlBulkCopy批量插入,批量更新数据解决方案
1) 根据取过来的数据(DataTable)字段创建临时表 ‘ tmp_表名‘
2)SqlBulkCopy数据导入临时表
3) 根据正式表主键对数据进行处理,删除相同主键数据,批量导入数据
4) 删除临时表
点击查看代码
public class DataBaseUtil
{
public event Action<string> LogHandler;
private dynamic GetCreateTableSql(DataTable table,string tmptableName, string tableName)
{
var colList = new List<string>();
var fieldNames = new List<string>();
foreach (DataColumn col in table.Columns)
{
fieldNames.Add(col.ColumnName);
}
var sql = string.Format(@" if object_id('{0}') is not null begin truncate table {0} drop table {0} end
select top 0 {1} into {0} from {2};
", tmptableName, string.Join(",", fieldNames),tableName);
return new { Sql = sql ,Fields= fieldNames };
}
public bool SqlBulkCopyUpgrade(string connectionString, string tableName,string keyField, DataTable table)
{
bool isSucc = false;
var tmpTableName = "tmp_" + tableName;
var msg = "";
try
{
#region 1.创建临时表
var filedObj = GetCreateTableSql(table, tmpTableName,tableName);
ExecuteNoQuerySql(connectionString, filedObj.Sql);
#endregion
LogHandler("新建临时表"+ tmpTableName+ "成功....");
#region 2.将his数据使用sqlbulk导入到临时表
//开始数据保存逻辑
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
SqlTransaction tran = conn.BeginTransaction();//开启事务
//在插入数据的同时检查约束,如果发生错误调用sqlbulkTransaction事务
SqlBulkCopy bulkCopy = new SqlBulkCopy(conn, SqlBulkCopyOptions.CheckConstraints, tran);
bulkCopy.DestinationTableName = tmpTableName;//代表要插入数据的表名
foreach (DataColumn dc in table.Columns) //传入上述table
{
bulkCopy.ColumnMappings.Add(dc.ColumnName, dc.ColumnName);//将table中的列与数据库表这的列一一对应
}
try
{
bulkCopy.WriteToServer(table);
tran.Commit();
isSucc = true;
}
catch (Exception ex)
{
tran.Rollback();
LogHandler("histoTmp" + ex.Message);
}
finally
{
bulkCopy.Close();
conn.Close();
}
if (!isSucc) throw new Exception($"histoTmp失败{tmpTableName}");
LogHandler("histoTmp" + tmpTableName + "成功....");
}
#endregion
#region 3.将临时表数据,批量插入到正式表
var fieldStr = string.Join(",", filedObj.Fields);
var sqlList = new List<string>();
//包含主键设置的话,在正式表里删除重复数据
if (!string.IsNullOrEmpty(keyField))
{
var delSql= string.Format(@"delete t1 from {0} t1 inner join tmp_{0} t2 on t2.{1}=t1.{1};",
tableName, keyField);
sqlList.Add(delSql);
}
var insertSql = string.Format(@" insert into {0}({1})select {1} from tmp_{0};", tableName, fieldStr);
sqlList.Add(insertSql);
sqlList.Add($"drop table tmp_{tableName}");
isSucc = ExecuteSqlTran(connectionString, sqlList) > 0;
if (!isSucc) throw new Exception($"TmpToMiddle失败{tableName}");
#endregion
}
catch (Exception e)
{
LogHandler(e.Message);
}
return isSucc;
}
#region QueryMult
public DataTable ReieveTableBySql(string connectionStr,string sql)
{
DataSet ds = SQLHelper.Query(sql, connectionStr);
if (ds == null || ds.Tables.Count == 0) return null;
var dt = ds.Tables[0];
return dt;
}
public int ExecuteSqlTran(string connectionStr, List<SqlExeInfo> SQLStringList)
{
using (SqlConnection conn = new SqlConnection(connectionStr))
{
conn.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
SqlTransaction tx = conn.BeginTransaction();
cmd.Transaction = tx;
var currentSql = "";
try
{
int count = 0;
for (int n = 0; n < SQLStringList.Count; n++)
{
var info = SQLStringList[n];
string strsql = info.ExeSql;
if (string.IsNullOrEmpty(strsql)) continue;
if (strsql.Trim().Length > 1)
{
cmd.CommandText = strsql;
currentSql = strsql;
//cmd.CommandType = CommandType.Text;
if (info.SqlParameters != null)
{
foreach (SqlParameter parm in info.SqlParameters)
cmd.Parameters.Add(parm);
}
count += cmd.ExecuteNonQuery();
}
}
tx.Commit();
return count;
}
catch (Exception ee)
{
var a = currentSql;
tx.Rollback();
LogHandler("执行trans报错:sql:" + currentSql + Environment.NewLine+
"问题:"+ ee.Message);
return 0;//throw;
}
}
}
public int ExecuteSqlTran(string connectionStr, List<string> SQLStringList)
{
var infos = new List<SqlExeInfo>();
for (var i = 0; i < SQLStringList.Count; i++)
{
infos.Add(new SqlExeInfo(){ExeSql =SQLStringList[i]});
}
return ExecuteSqlTran(connectionStr,infos);
}
#endregion
}
分类:
sqlserver
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类