实际上,我以前写的有现成的函数来完成这个工作, 但是, 可惜那函数只能在VS2005 下工作, 在2003下面无效,无效的原因是,vs2003 的DataTable.Rows[i].SetAdded() 方法不存在. 也就是说, 你没有办法去更改一行的RowState, 而从excel 读到的dataTable的 行状态"默认" 是unChanged.
如果不信, 你也可以尝试去google或百度上搜一下试试看, 关于这个功能的贴子真是少得可怜,大约大家都换用vs2005了吧, 我找了半天, 零零碎碎地找到一些信息, 这些信息都指向DataTable.GetChanges(RowState) 函数, 由于都是语焉不详, 所以我高兴地认为, 这个函数能将表的所有行的状态都设置为参数所指定的RowState, 就像我原来的函数用一个for循环为每一行调用SetAdded 的效果一样, 我一边还惭愧, 以前用了那么笨的办法. 然而心底却在奇怪, 微软怎么会起了这么笨的一个函数名.
一番测试后, 终于弄明白原来不是微软笨,而是我弄错了, GetChanges函数果然是用来Get, 而不是set的, 它返回母表中指定状态的行组成的子表, 也就是说, 刚才的查找白费了.
再找了一会儿, 借助于Mitch Milam 先生十分专业的一篇文章, 终于找到了正确的solution, 这篇文章的url:
http://blogs.infinite-x.net/2006/09/21/the-saga-of-net-dataadapterupdate-and-multiple-tables/print/
说它专业, 是因为这篇文章几乎是以正规科技论文的格式来写的, 虽然我自己写论文的时候很讨厌麻烦的格式, 但是阅读的时候, 却不得不承认, 这种严谨的格式读起来实在是愉快地多. ----废话少说, 问题的关键在于行状态, 从excel 读取后成了unchanged, 而且又无法修改, 问题就在于读取. 原来数据适配器有一个AcceptChangesDuringFill 属性, 这个属性默认为true, 所以调用Fill 方法后, 它就自动地AcceptChange了 , 然后行状态就变成unchanged了, 只要把这个属性置为false, fill 后, 就可以保持行状态为Added, 然后在update 函数里就不需要考虑行状态了.
以下为不太熟悉这两种操作的朋友列出源代码, 为了阅读方便,去掉了错误检查部分的代码,但在实际应用中, try语句是不可缺少的:
<0>调用代码:
1string path="upload";
2DataTable dt=ImportFromExcel(path);
3string selectCommand="SELECT * FROM T1";
4UpdateToDataBase(selectCommand,dt);
2DataTable dt=ImportFromExcel(path);
3string selectCommand="SELECT * FROM T1";
4UpdateToDataBase(selectCommand,dt);
<1> 从excel 读取数据
1DataTable ImportFromExcel(string path)
2{
3 path=Server.MapPath(path);
4 upload1.PostFile.SaveAs(path);
5
6 string connString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + path +";Extended Properties='Excel 8.0;HDR=yes;IMEX=1;'";
7 string selectCommand = " SELECT * FROM [Sheet1$] ";
8 DataTable dt=new DataTable();
9
10 System.Data.OleDb.OleDbConnection conn=new System.Data.OleDb.OleDbConnection(connString);
11 conn.Open();
12 System.Data.OleDb.OleDbCommand cmd = new System.Data.OleDb.OleDbCommand(selectCommand, conn);
13 System.Data.OleDb.OleDbDataAdapter adt = new System.Data.OleDb.OleDbDataAdapter(cmd);
14 adt.AcceptChangesDuringFill=false;
15 adt.Fill(dt);
16 conn.Close();
17 System.IO.File.Delete(path);
18 return dt;
19
20}
这里面的trick 就是第14 行. 2{
3 path=Server.MapPath(path);
4 upload1.PostFile.SaveAs(path);
5
6 string connString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + path +";Extended Properties='Excel 8.0;HDR=yes;IMEX=1;'";
7 string selectCommand = " SELECT * FROM [Sheet1$] ";
8 DataTable dt=new DataTable();
9
10 System.Data.OleDb.OleDbConnection conn=new System.Data.OleDb.OleDbConnection(connString);
11 conn.Open();
12 System.Data.OleDb.OleDbCommand cmd = new System.Data.OleDb.OleDbCommand(selectCommand, conn);
13 System.Data.OleDb.OleDbDataAdapter adt = new System.Data.OleDb.OleDbDataAdapter(cmd);
14 adt.AcceptChangesDuringFill=false;
15 adt.Fill(dt);
16 conn.Close();
17 System.IO.File.Delete(path);
18 return dt;
19
20}
<2>提交DataTable 到数据库
1void UpdateToDataBase(string sql,DataTable dt)
2{
3 string connString=GetConnectionString();
4
5 System.Data.SqlClient.SqlConnection con = new System.Data.SqlClient.SqlConnection(connString);
6 System.Data.SqlClient.SqlDataAdapter adt = new System.Data.SqlClient.SqlDataAdapter(sql, con);
7 System.Data.SqlClient.SqlCommandBuilder builder = new System.Data.SqlClient.SqlCommandBuilder(adt);
8 adt.InsertCommand=builder.GetInsertCommand();
9 con.Open();
10 adt.Update(dt).ToString();
11 con.Close();
12}
13
2{
3 string connString=GetConnectionString();
4
5 System.Data.SqlClient.SqlConnection con = new System.Data.SqlClient.SqlConnection(connString);
6 System.Data.SqlClient.SqlDataAdapter adt = new System.Data.SqlClient.SqlDataAdapter(sql, con);
7 System.Data.SqlClient.SqlCommandBuilder builder = new System.Data.SqlClient.SqlCommandBuilder(adt);
8 adt.InsertCommand=builder.GetInsertCommand();
9 con.Open();
10 adt.Update(dt).ToString();
11 con.Close();
12}
13