使用OleDbDataAdapter更新DataTable C#

我一直在尝试使用OleDbDataAdapter来更新DataTable,但对这些命令感到困惑。 因为我有时从不同的表中获取信息,所以我不能使用CommandBuilder。 所以我试图在我的on上创建命令,但发现参数很难。 DataTable.GetChanges返回需要使用INSERT或UPDATE命令的行 – 我想我无法区分它们。 我需要你完成以下内容:

DataTable dt = new DataTable(); OleDbDataAdapter da = new OleDbDataAdapter(); // Here I create the SELECT command and pass the connection. da.Fill(dt); // Here I make changes (INSERT/UPDATE) to the DataTable (by a DataGridView). da.UpdateCommand = new OleDbCommand("UPDATE TABLE_NAME SET (COL1, COL2, ...) VALUES (@newVal1, @newVal2, ...) WHERE id=@id"); // How can I use the values of the current row (that the da is updating) as the parameters (@newVal1, @newVal2, id....)? 

非常感谢你!

数据适配器可以与数据表一起使用。 因此,我实际上已经将我的一起包装成一个class级并且运作良好。 除了我的东西的复杂性,这里有一个可能会帮助你的片段。 添加参数时,您可以标识数据来自DataTable的列源。 这样,当记录在内部标识为“已添加”或“已更新”(或“已删除”)时,在构建SQL插入/更新/删除命令时,它将从相应行的列中提取数据。

例如。 假设我有一个DataTable,主键是“MyID”,并且列有“ColX,ColY,ColZ”。 我创建我的DataAdapter并构建我的选择,更新,删除命令,如…(?是参数的占位符)

 DataAdapter myAdapter = new DataAdapter() myAdapter.SelectCommand = new OleDbCommand(); myAdapter.InsertCommand = new OleDbCommand(); myAdapter.UpdateCommand = new OleDbCommand(); myAdapter.DeleteCommand = new OleDbCommand(); myAdapter.SelectCommand.CommandText = "select * from MyTable where MyID = ?"; myAdapter.InsertCommand.CommandText = "insert into MyTable ( ColX, ColY, ColZ ) values ( ?, ?, ? )"; myAdapter.UpdateCommand.CommandText = "update MyTable set ColX = ?, ColY = ?, ColZ = ? where MyID = ?"; myAdapter.DeleteCommand.CommandText = "delete from MyTable where MyID = ?"; 

现在,每个人都必须拥有各自的“参数”。 参数必须以与其对应的“?”相同的顺序添加。 占位。

//虽然我为准备参数设置了伪造的值,但它仅用于//数据类型。 它在应用更改时会通过数据适配器进行更改

 OleDbParameter oParm = new OleDbParameter( "myID", -1 ); oParm.DbType = DbType.Int32; oParm.SourceColumn = "myID"; // <- this is where it looks back to source table's column oParm.ParameterName = "myID"; // just for consistency / readability reference myAdapter.SelectCommand.Parameters.Add( oParm ); 

根据其类型... char,int,double等等,为其余的参数做类似的事情

同样,我喜欢一个包装类,它基于每个表来处理管理......简而言之

 public myClassWrapper { protected DataTable myTable; protected DataAdapter myAdapter; ... more ... protected void SaveChanges() { } } 

它比这更复杂,但在“SaveChanges”期间,数据表和dataAdapter为了它们自己的目的是同步的。 现在,刷新数据。 我检查表的状态,然后您可以将整个表传递给dataAdapter进行更新,它将遍历所有已更改的记录并推送相应的更改。 尽管如此,您还是必须捕获任何可能的数据错误。

 myAdapter.Update( this.MyTable ); 

当它找到每个“已更改”记录时,它会从列源中提取值,这些值由在传递给适配器进行处理的表中找到的参数标识。

希望这能让你在遇到的问题上大放异彩。

----评论反馈----

我会将您的更新放在try / catch中,然后进入程序以查看exception是什么。 消息adn /或错误的内部exception可能会提供更多信息。 但是,尝试将UPDATE简化为仅包含带有WHERE“Key”元素的FEW字段。

另外,我从第一部分答案中错过了这一点。 您可能必须标识数据表的“PrimaryKey”列。 为此,它需要DataTable的属性以及表示表的主键的列数组。 我做的是......

 // set the primary key column of the table DataColumn[] oCols = { myDataTbl.Columns["myID"] }; myDataTbl.PrimaryKey = oCols; 

我会为你的UPDATE注释掉你的完整更新字符串及其所有参数。 然后,使用与仅设置2-3列和where子句的示例一样简单地构建它

 myAdapter.UpdateCommand.CommandText = "update MyTable set ColX = ?, ColY = ? where MyID=?"; Add Parameter object for "X" Add Parameter object for "Y" Add Parameter object for "MyID" 

选择像int或char这样的字段,这样它们对数据类型转换的问题概率最小,然后,一旦有效,尝试添加所有“int”和“character”列...然后添加任何其他列。 另外,你反对哪个数据库。 有些数据库不使用“?” 作为命令中的占位符但使用“命名”参数,有些使用

 "actualColumn = @namedCol" or even "actualColumn = :namedCol" 

希望这能让你超越驼峰......

您可以使用String.Format方法替换代码中的@newVal1, @newVal2, ... ,例如da.UpdateCommand = new OleDbCommand(String.Format("UPDATE TABLE_NAME SET (COL1, COL2, ...) VALUES ({0}, {1}, ...) WHERE id=@id",OBJECT_ARRAY_CONTAINING_VALUES_FROM_THEDG));

[Eidt每条评论]

要处理row[0]row[1]您需要一个循环,如:

for(i=0; i

da.UpdateCommand = new OleDbCommand(String.Format("UPDATE ... ",row[i]);

da.Update(dt);

}