C# 使用SqlDataAdapter批量更新数据,出现当传递具有新行的 DataRow 集合时,更新要求有效的 InsertCommand,代码如下:
System.Data.SqlClient.SqlDataAdapter sda = new System.Data.SqlClient.SqlDataAdapter();
SqlCommandBuilder objcmdBuilder;
SqlCommand scmd = new SqlCommand();//定义一个SqlCommand的实例,以便绑定
scmd.CommandType = CommandType.Text;
scmd.Connection = new SqlConnection(GetConnectionStrings());
scmd.Parameters.Add("@Id", SqlDbType.VarChar, 50, "Id");
scmd.Parameters.Add("@PayId", SqlDbType.VarChar, 50, "PayId");
scmd.Parameters.Add("@CostCenterName", SqlDbType.VarChar, 50, "CostCenterName");
scmd.Parameters.Add("@Name", SqlDbType.NVarChar, 8000, "Name");
scmd.Parameters.Add("@WorkNumber", SqlDbType.VarChar, 50, "WorkNumber");
scmd.Parameters.Add("@PayMonth", SqlDbType.VarChar, 50, "PayMonth");
scmd.CommandText = string.Format(@"
UPDATE HouGe_PaySheedDetail SET
CostCenterName=@CostCenterName,
Name=@Name,
WorkNumber=@WorkNumber,
PayMonth=@PayMonth
where Id=@Id");
sda.UpdateCommand = scmd;
sda.Update(dt);// 此处的dt是从其他地方传过来的,是需要更新到数据库中的,错误就发生在这个地方,试过很多方法都不行,网上的很多方法也都是不行,有谁做过这样的操作呢??
sda.Dispose();
现在我研究出了一种效率比较高的方法,来实现大批量数据更新的问题,代码如下:
/// <summary>
/// 批量更新
/// </summary>
/// <param name="dt"></param>
/// <param name="columName"></param>
/// <param name="tableName"></param>
/// <param name="primaryKey"></param>
public void BatchUpdate(DataTable dt, string[] columName, string tableName, string primaryKey)
{
using (SqlCommand command = new SqlCommand("", _sqlConnection))
{
try
{
var tempTableName = $"#Temp{DateTime.Now.ToString("yyyMMddHHmmss")}";
var updateSetSql = new StringBuilder();
var updateFormSql = new StringBuilder();
updateSetSql.AppendFormat(@" UPDATE A SET");
foreach (var item in columName)
{
updateSetSql.AppendFormat(@" A." + item + "=Temp." + item + ",");
}
var str = updateSetSql.ToString();
str = str.Substring(0, str.Length - 1);
updateSetSql.Remove(0, updateSetSql.Length);
updateFormSql.AppendFormat(str);
updateFormSql.AppendFormat(@" FROM " + tableName + " A ");
updateFormSql.AppendFormat(@" INNER JOIN " + tempTableName + " Temp ");
updateFormSql.AppendFormat(@" ON A." + primaryKey + "=Temp." + primaryKey + ";");
updateFormSql.AppendFormat(@" DROP TABLE " + tempTableName + " ");
command.Transaction = _sqlTransaction;
//构建临时表
command.CommandText = $"SELECT * INTO {tempTableName} FROM " + tableName + " WHERE 1 = 2;";
command.ExecuteNonQuery();
//插入临时表
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(_sqlConnection, SqlBulkCopyOptions.KeepIdentity, _sqlTransaction))
{
bulkCopy.DestinationTableName = tempTableName;
bulkCopy.BatchSize = dt.Rows.Count;
if (dt != null && dt.Rows.Count != 0)
{
for (int i = 0; i < dt.Columns.Count; i++)
{
bulkCopy.ColumnMappings.Add(dt.Columns[i].ColumnName, dt.Columns[i].ColumnName);
}
bulkCopy.WriteToServer(dt);
bulkCopy.Close();
}
}
//从临时表更新到原表,并删除临时表
command.CommandTimeout = 300;
command.CommandText = updateFormSql.ToString();
command.ExecuteNonQuery();
}
catch (Exception ex)
{
//throw ex;
}
finally
{
//conn.Close();
}
}
}
把dt中的数据行状态(DataRowState)改成Modified试试
哦,这个试过了,但是这个字段是只读的,不可修改。还有没有其他更好的方法来批量Update数据呢?
@gyangjing: dt.Rows[0].SetModified();
@会长: 嗯,这个试过了,是这样改变状态的,不过这种方法执行的效率很低,我又想出了一个折中的办法,能提高不少效率
Sqlcommandbuilder类没有正确使用,需要一个查询语句为基础实例化
那个查询语句是必须要的吗?