一、简述
在项目中有一个需要导入数据包的需求,数据包是一个XML的文件,里面存储有数据,那么读取文件后就形成一个DataTable,然后改怎么把这个DataTable的数据批量插入到数据库里面去呢?用一个循环?循环虽然简单,但总结的有点别扭,所以还是用SqlCommandBuilder、SqlDataAdapter.update来批量插入数据吧。
二、内容
首先数据库的原数据
然后批量插入数据的代码
private string con = "Data Source=.;Initial Catalog=TestDatabase;Integrated Security=True";
private void DataBatchUpdate()
{
// 假数据
DataTable dt = new DataTable();
dt.Columns.Add("id", typeof(int));
dt.Columns.Add("testName");
DataRow dr = dt.NewRow();
dr["id"] = "1";
dr["testName"] = "白白";
dt.Rows.Add(dr);
SqlConnection sqlCon = new SqlConnection(con);
SqlDataAdapter sqlDa = new SqlDataAdapter("select * from testDataTable ", sqlCon);
DataSet sqlds = new DataSet();
sqlDa.Fill(sqlds);
// 数据库数据
DataTable databaseData = sqlds.Tables[0];
databaseData.Merge(dt);
SqlCommandBuilder sqlcb = new SqlCommandBuilder(sqlDa);
sqlDa.Update(databaseData);
}
得出来的数据,里面就新增了一条数据
这里主要是 Merge 起来合并两张Table表,然后由SqlCommandBuilder与Update()来更新到数据。然而,函数Update() 是根据DataTable的RowState来更新表的。当用Merge合并了两张表后,各行的RowState就像下图
这里,先在原来代码的基础添加几行代码
private string con = "Data Source=.;Initial Catalog=TestDatabase;Integrated Security=True";
private void DataBatchUpdate()
{
// 假数据
DataTable dt = new DataTable();
dt.Columns.Add("id", typeof(int));
dt.Columns.Add("testName");
DataRow dr = dt.NewRow();
dr["id"] = "1";
dr["testName"] = "白白";
dt.Rows.Add(dr);
SqlConnection sqlCon = new SqlConnection(con);
SqlDataAdapter sqlDa = new SqlDataAdapter("select * from testDataTable ", sqlCon);
DataSet sqlds = new DataSet();
sqlDa.Fill(sqlds);
// 数据库数据
DataTable databaseData = sqlds.Tables[0];
databaseData.Merge(dt);
// 显示表格没一行的状态
databaseData.Columns.Add("updatedSate");
for (int i = 0; i < databaseData.Rows.Count; i++)
{
DataRow updatedRow = databaseData.Rows[i];
updatedRow["updatedSate"] = updatedRow.RowState;
}
//SqlCommandBuilder sqlcb = new SqlCommandBuilder(sqlDa);
//sqlDa.Update(databaseData);
gridData.DataSource = databaseData;
gridData.DataBind();
}
得出的结果则显示最后一条的状态是 Added,所以就作为新数据插入到数据库去。
那么,如果只是批量插入数据的话
SqlDataAdapter sqlDa = new SqlDataAdapter("select * from testDataTable ", sqlCon);
还可以这么写,就是获取到数据库表中的结构就可以了。
SqlDataAdapter sqlDa = new SqlDataAdapter("select * from testDataTable where 1=2", sqlCon);
那么,如果只是单纯的批量插入数据库就简单多了,可是项目的导入数据包功能,如果用户是重复导入了呢?又或者导入的数据当中只有几个单元格的数据跟数据库的数据不同的呢?这该怎么解决?嗯??在代码中写个几句代码判断导入的数据在数据库表中是否存在,存在就把数据库表中的数据删掉,再新插入进去? - - ! 显然不靠谱。
后来就发现了有一种很神奇的方法,因为代码中的Update()是根据RowState来判断是否增删改的,上面只用到了“增”,那么只要RowsState是“改”就可以了。
首先代码
private string con = "Data Source=.;Initial Catalog=TestDatabase;Integrated Security=True";
private void DataBatchUpdate()
{
// 假数据
DataTable dt = new DataTable();
dt.Columns.Add("id", typeof(int));
dt.Columns.Add("testName");
DataRow dr = dt.NewRow();
dr["id"] = "1";
dr["testName"] = "白白";
dt.Rows.Add(dr);
SqlConnection sqlCon = new SqlConnection(con);
SqlDataAdapter sqlDa = new SqlDataAdapter("select * from testDataTable ", sqlCon);
DataSet sqlds = new DataSet();
sqlDa.Fill(sqlds);
// 数据库数据
DataTable databaseData = sqlds.Tables[0];
databaseData.PrimaryKey = new DataColumn[] { databaseData.Columns["id"] }; //设置DataTable的主键
databaseData.Merge(dt);
// 显示表格没一行的状态
databaseData.Columns.Add("updatedSate");
for (int i = 0; i < databaseData.Rows.Count; i++)
{
DataRow updatedRow = databaseData.Rows[i];
updatedRow["updatedSate"] = updatedRow.RowState;
}
SqlCommandBuilder sqlcb = new SqlCommandBuilder(sqlDa);
sqlDa.Update(databaseData);
gridData.DataSource = databaseData;
gridData.DataBind();
}
关键是为DataTable设置主键,然后Merge()就会自动修改,其RowState就变成了“改”,并且Name也随之变了。
《=修改后
《=修改前
这样就可以实现在相同的ID下自动批量更新数据的效果。 注:Update()更新数据的时候,数据库表中结构要有主键才可以。