高分解决dataset更新数据库问题 各位大虾,小弟用c#(不是asp.net,是form)写了个程序,就是一个access中有数据,我使用dataset1把数据提出来了,如何更新数据库啊,最好是用olecommend,因为我是批量更改,(不能通过绑定datagird更新),我看了网上好多人提问,感觉好像都不是写的很清楚哈,最好是能给点代码,谢谢了 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 不好意思,写错了,是OleDbCommandBuilder,不是olecommend void Page_Load(object sender, System.EventArgs e){ SqlConnection conn = new SqlConnection("server=localhost;uid=sa;pwd=;database=db"); SqlDataAdapter da = new SqlDataAdapter(); SqlCommand cmd = new SqlCommand("select Id AS id, Name AS name from table",conn); DataSet ds = new DataSet(); conn.Open(); da.SelectCommand = cmd; da.Fill(ds,"table"); for(int i=0; i<ds.Tables["table"].Rows.Count; i++) { Response.Write(ds.Tables["table"].Rows[1]+"<br>"); } for(int i=0; i<ds.Tables["table"].Rows.Count; i++) { ds.Tables["table"].Rows.BeginEdit(); ds.Tables["table"].Rows[1] = "**********"; ds.Tables["table"].Rows.EndEdit(); } String strUpdateSql = "Update table set Name=@name where Id=@id"; cmd = new SqlCommand(strUpdateSql , conn); cmd.Parameters.Add("@id",SqlDbType.Int,4, "id"); cmd.Parameters.Add("@name ",SqlDbType.Char,10, "name "); da.UpdateCommand = cmd; da.Update(ds, "table"); ds.AcceptChanges(); conn.Close(); } for(int i=0; i <ds.Tables["table"].Rows.Count; i++) { ds.Tables["table"].Rows.BeginEdit(); ds.Tables["table"].Rows[1] = "**********"; ds.Tables["table"].Rows.EndEdit(); } 这样写,更新数据库好像很慢哦,因为是一条一条更新的,如果数据量很大的话,时间很长,因为我的数据量很大,所以不能采用这种方法 我的数据库表是这样的:字段是:索引 企业名字 1月 2月 3月...12月,是每月根据当月的数据,填充到当月的字段中去,其中,企业名字可能每月都有变化,数据量比较大,如果是先使用下面的语句的话, String strUpdateSql = "Update table set Name=@name where Id=@id"; cmd = new SqlCommand(strUpdateSql , conn); 会非常慢,因为要每月都要先做一个企业名字的比对(大概有几千条数据),如果名字对了,就在相应的月里面加入数据,如果没有的话,就要在数据库的最后一条里面加入新数据,所以你的方法可能不得行。 用你的办法更慢,实际上是如果对数据做了更新才会去更新数据库,如果没有就不做修改。当然DataSet中有这么一个标识,但是我更喜欢直接用ADO.NET直接操作,代码更容易维护。 我用的是access,不是sql,好像语句有点不对,另外,我因为是用的OleDbCommandBuilder来更新数据,代码如下:private void FormMain_Load(object sender, EventArgs e) { string file_name = Application.StarupPath + @"\test.mdb"; //本地数据库在bin里面string password = "123"; string ConnectionString = string.Format("Provider=Microsoft.JET.OLEDB.4.0;Data Source='{0}';Persist Sercurity Info=false; JET OLEDB:Database Password={1}", file_name, password); conn = new OleDbConnection(ConnectionString); string sql = "SELECT * FROM test";//test为表名da = new OleDbDataAdapter(sql, conn); ds = new DataSet(); da.Fill(ds); cb = new OleDbCommandBuilder(da); } private void btnImport_Click(object sender,EventArgs e) //更新数据库{ DataTable dt = this.dataset1.Tables[0]; //dataset1是我新设立的一个DataSet,取的是excel里面的数据 for (int i = 0; i < dt.Rows.Count; i++) { ds.Tables[0].Rows.Add(dt.Rows[i].ItemArray); Application.DoEvents(); } da.Update(ds);//在此处更新数据 MessageBox.Show("提示操作成功。"); }//用上面的代码,在数据库里面没数据的时候,更新很快,运行成功但是数据库里面有数据的时候,我添加了一条语句ds.Clear();在for循环的前面for (int i = 0; i < dt.Rows.Count; i++) { ds.Tables[0].Rows.Add(dt.Rows[i].ItemArray); Application.DoEvents(); } da.Update(ds);//在此处更新数据 MessageBox.Show("提示操作成功。"); 然后运行,就会报错,说数据库重复主键不能更新成功,我感觉 da.Update(ds);好像在把dataset1里面的数据又重新写入数据库,而不是只改变有变化的样,但是我已经把ds清空了,还是不得行。不过把数据库先用delete清空,运行上面的数据,才能da.Update(ds);成功样,请问下各位高手,这是怎么回事, delete清空指的是把数据库全部删除 这样吧,你不要用ds.Clear(),用ds.Tables[0].Rows.Clear()就会清除相应的数据行,里面就不会有数据了,如果是用ds.Clear()会清除所有的表数据的。 或者你试下以下代码:if (ds!= null && ds.Tables.Count > 0){ ds.Tables["表名"].Rows.Clear(); //ds.Tables.Clear();} 兄弟,还有个地方你要注意啊:你在代码中写到:private void FormMain_Load(object sender, EventArgs e) { string file_name = Application.StarupPath + @"\test.mdb"; //本地数据库在bin里面 string password = "123"; string ConnectionString = string.Format("Provider=Microsoft.JET.OLEDB.4.0;Data Source='{0}';Persist Sercurity Info=false; JET OLEDB:Database Password={1}", file_name, password); conn = new OleDbConnection(ConnectionString); string sql = "SELECT * FROM test";//test为表名 da = new OleDbDataAdapter(sql, conn); ds = new DataSet(); da.Fill(ds); cb = new OleDbCommandBuilder(da); } 标红色粗体部分你这是在窗体加载时显示全部的数据,这个没有必要,而且速度也会很慢的,如果你是想导入数据的话就直接用:string sql="SELECT * FROM test WHERE 1=2";这样就会返回一个空行的数据集,里面就没有数据,如果导入成功后再导入另个一个excel档案就要清除ds里面的内容,否则会出现数据重复的问题(因为之前ds已经读取一个档案的数据,且这个档案的内容已经导入到数据库,再次导入肯定会出现主键冲突的问题)ds.Tables["表名"].Rows.Clear()应该就可以了 DataTable dt = this.dataset1.Tables[0]; //dataset1是我新设立的一个DataSet,取的是excel里面的数据 这个也要注意和上面一样的问题,如果已经读取过数据就要将它的数据清除再读新的。 你循环datatable的时候,判断datarow有没有被更新过,如果有就用ado.net update,否则就忽略! 兄弟,我终于查出你的是什么问题了,主要是数据库的列名问题,我看到你的wf表中有一个名为1的列 所以在编辑时,比如你的代码: DataRow dr = ds.Tables[0].Rows[0]; dr.BeginEdit(); dr["1"]=333; dr.EndEdit(); da.Update(ds); 这段代码中dr["1"]=333可能同时指向第二列,因为第二列有两种表示方式dr[1]或dr["1"]都可以,程序会认为你同时编辑这一列就会出现并发冲突的问题,建议你把数据表的第二列的列名另外改一个名称,应该就可以了,我试过了,以后也少用这样的列名。 不用客气了,我先记下你的QQ,到时我上Q的时候加你啊! winform 用户控件问题 求解 求一条正则表达式 能否直接把vs2005的快捷键设置为Delphi的一样? 怎么获取打印机和打印状态,还有其对应的打印文件的队列? 解压缩程序不好用附代码 100分求个net 2.0以上的oledbhelper,项目急,实在来不及弄了,, 高分求解dataGrid! 在下面加什么代码,可以将日期存入数据库呢!?谢谢! 消息队列问题 求助 winfrom程序运行到一定时间错误 C#开发CE/Mobile招人~ treeview节点的状态问题
{
SqlConnection conn = new SqlConnection("server=localhost;uid=sa;pwd=;database=db");
SqlDataAdapter da = new SqlDataAdapter();
SqlCommand cmd = new SqlCommand("select Id AS id, Name AS name from table",conn);
DataSet ds = new DataSet();
conn.Open();
da.SelectCommand = cmd;
da.Fill(ds,"table");
for(int i=0; i<ds.Tables["table"].Rows.Count; i++)
{
Response.Write(ds.Tables["table"].Rows[1]+"<br>");
}
for(int i=0; i<ds.Tables["table"].Rows.Count; i++)
{
ds.Tables["table"].Rows.BeginEdit();
ds.Tables["table"].Rows[1] = "**********";
ds.Tables["table"].Rows.EndEdit();
}
String strUpdateSql = "Update table set Name=@name where Id=@id";
cmd = new SqlCommand(strUpdateSql , conn);
cmd.Parameters.Add("@id",SqlDbType.Int,4, "id");
cmd.Parameters.Add("@name ",SqlDbType.Char,10, "name ");
da.UpdateCommand = cmd;
da.Update(ds, "table");
ds.AcceptChanges();
conn.Close();
}
{
ds.Tables["table"].Rows.BeginEdit();
ds.Tables["table"].Rows[1] = "**********";
ds.Tables["table"].Rows.EndEdit();
}
这样写,更新数据库好像很慢哦,因为是一条一条更新的,如果数据量很大的话,时间很长,因为我的数据量很大,所以不能采用这种方法
String strUpdateSql = "Update table set Name=@name where Id=@id";
cmd = new SqlCommand(strUpdateSql , conn);
会非常慢,因为要每月都要先做一个企业名字的比对(大概有几千条数据),如果名字对了,就在相应的月里面加入数据,如果没有的话,就要在数据库的最后一条里面加入新数据,所以你的方法可能不得行。
private void FormMain_Load(object sender, EventArgs e)
{
string file_name = Application.StarupPath + @"\test.mdb"; //本地数据库在bin里面
string password = "123";
string ConnectionString = string.Format("Provider=Microsoft.JET.OLEDB.4.0;Data Source='{0}';Persist Sercurity Info=false; JET OLEDB:Database Password={1}", file_name, password);
conn = new OleDbConnection(ConnectionString);
string sql = "SELECT * FROM test";//test为表名
da = new OleDbDataAdapter(sql, conn);
ds = new DataSet();
da.Fill(ds);
cb = new OleDbCommandBuilder(da);
}
private void btnImport_Click(object sender,EventArgs e) //更新数据库
{
DataTable dt = this.dataset1.Tables[0]; //dataset1是我新设立的一个DataSet,取的是excel里面的数据
for (int i = 0; i < dt.Rows.Count; i++)
{
ds.Tables[0].Rows.Add(dt.Rows[i].ItemArray);
Application.DoEvents();
}
da.Update(ds);//在此处更新数据
MessageBox.Show("提示操作成功。");
}
//用上面的代码,在数据库里面没数据的时候,更新很快,运行成功
但是数据库里面有数据的时候,我添加了一条语句
ds.Clear();在for循环的前面
for (int i = 0; i < dt.Rows.Count; i++)
{
ds.Tables[0].Rows.Add(dt.Rows[i].ItemArray);
Application.DoEvents();
}
da.Update(ds);//在此处更新数据
MessageBox.Show("提示操作成功。");
然后运行,就会报错,说数据库重复主键不能更新成功,
我感觉 da.Update(ds);好像在把dataset1里面的数据又重新写入数据库,而不是只改变有变化的样,但是我已经把ds清空了,还是不得行。
不过把数据库先用delete清空,运行上面的数据,才能da.Update(ds);成功样,
请问下各位高手,这是怎么回事,
if (ds!= null && ds.Tables.Count > 0)
{
ds.Tables["表名"].Rows.Clear();
//ds.Tables.Clear();
}
private void FormMain_Load(object sender, EventArgs e)
{
string file_name = Application.StarupPath + @"\test.mdb"; //本地数据库在bin里面
string password = "123";
string ConnectionString = string.Format("Provider=Microsoft.JET.OLEDB.4.0;Data Source='{0}';Persist Sercurity Info=false; JET OLEDB:Database Password={1}", file_name, password);
conn = new OleDbConnection(ConnectionString);
string sql = "SELECT * FROM test";//test为表名
da = new OleDbDataAdapter(sql, conn);
ds = new DataSet();
da.Fill(ds);
cb = new OleDbCommandBuilder(da);
}
标红色粗体部分你这是在窗体加载时显示全部的数据,这个没有必要,而且速度也会很慢的,如果你是想导入数据的话就直接用:string sql="SELECT * FROM test WHERE 1=2";这样就会返回一个空行的数据集,里面就没有数据,如果导入成功后再导入另个一个excel档案就要清除ds里面的内容,否则会出现数据重复的问题(因为之前ds已经读取一个档案的数据,且这个档案的内容已经导入到数据库,再次导入肯定会出现主键冲突的问题)ds.Tables["表名"].Rows.Clear()应该就可以了
这个也要注意和上面一样的问题,如果已经读取过数据就要将它的数据清除再读新的。
所以在编辑时,比如你的代码:
DataRow dr = ds.Tables[0].Rows[0];
dr.BeginEdit();
dr["1"]=333;
dr.EndEdit();
da.Update(ds); 这段代码中dr["1"]=333可能同时指向第二列,因为第二列有两种表示方式dr[1]或dr["1"]都可以,程序会认为你同时编辑这一列就会出现并发冲突的问题,建议你把数据表的第二列的列名另外改一个名称,应该就可以了,我试过了,以后也少用这样的列名。