简体   繁体   English

使用OleDbDataAdapter更新数据表C#

[英]Using OleDbDataAdapter to update a DataTable C#

I have been trying to use OleDbDataAdapter to update a DataTable but got confused about the commands. 我一直在尝试使用OleDbDataAdapter更新DataTable,但对命令感到困惑。 Since I sometimes get info from diffrent tables I can't use a CommandBuilder. 由于有时我会从不同的表中获取信息,因此无法使用CommandBuilder。 So I have tried to create the commands on my on but found it hard with the parameters. 因此,我尝试在自己的计算机上创建命令,但发现使用参数很难。 DataTable.GetChanges returns rows that needs to use an INSERT or an UPDATE command - I guess I can't distinct between them. DataTable.GetChanges返回需要使用INSERT或UPDATE命令的行-我想我无法区分它们。 I need you to complete the following: 我需要您完成以下操作:

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....)?

Thank you very much! 非常感谢你!

The data adapter can work in conjunction with the datatable. 数据适配器可以与数据表一起使用。 As such, I've actually wrapped mine together into a class and works quite well. 因此,我实际上将我的课程包装在一起,并且效果很好。 Aside from the complexities of my stuff, here's a snippet that might help you along. 除了我的内容的复杂性之外,以下代码段可能会对您有所帮助。 When adding a parameter, you can identify the column source that the data is coming from FROM the DataTable. 添加参数时,您可以标识数据来自FROM DataTable的列源。 This way, when a record is internally identified as "Added" or "Updated" (or "Deleted"), when you build your SQL Insert/Update/Delete commands, it will pull the data from the columns from the respective rows. 这样,当一条记录在内部被标识为“已添加”或“已更新”(或“已删除”)时,在构建SQL插入/更新/删除命令时,它将从相应行的列中提取数据。

For example. 例如。 Say I have a DataTable, primary Key is "MyID" and has columns "ColX, ColY, ColZ". 假设我有一个数据表,主键为“ MyID”,列为“ ColX,ColY,ColZ”。 I create my DataAdapter and build out my select, update, delete commands something like... (? is a place-holder for the parameters) 我创建我的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 = ?";

Now, each has to have their respective "Parameters". 现在,每个人都必须具有各自的“参数”。 The parameters have to be addded in the same sequence as their corresponding "?" 参数必须以与它们相应的“?”相同的顺序添加。 place-holders. 占位符。

// Although I'm putting in bogus values for preparing the parameters, its just for // data type purposes. //虽然我在输入伪造的值来准备参数,但是它只是出于数据类型的目的。 It does get changed through the data adapter when it applies the changes 应用更改后,它确实会通过数据适配器进行更改

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 );

do similar for rest of parameters based on their types... char, int, double, whatever 根据参数的类型对其余参数执行类似操作... char,int,double,无论

Again, I have like a wrapper class that handles managment on a per-table basis... in brief 再次,我就像一个包装器类,该包装器按表处理管理...简而言之

public myClassWrapper
{
    protected DataTable myTable;
    protected DataAdapter myAdapter;
    ... more ...

    protected void SaveChanges()
    {
    }
}

Its more complex than just this, but during the "SaveChanges", The datatable and dataAdapter are in synch for their own purposes. 它不仅复杂,而且在“ SaveChanges”期间,datatable和dataAdapter出于自己的目的而同步。 Now, flushing the data. 现在,刷新数据。 I check for the status of the table and then you can pass the entire table to the dataAdapter for update and it will cycle through all changed records and push respective changes. 我检查表的状态,然后可以将整个表传递给dataAdapter进行更新,它将遍历所有更改的记录并推送相应的更改。 You'll have to trap for whatever possible data errors though. 但是,您必须捕获任何可能的数据错误。

myAdapter.Update( this.MyTable );

As it finds each "changed" record, it pulls the values from the Column Source as identified by the parameter that is found in the table being passed to the adapter for processing. 找到每个“已更改”的记录时,它从列源中提取值,该值由传递到适配器进行处理的表中的参数所标识。

Hopefully this has given you a huge jump on what you are running into. 希望这可以让您对正在遇到的问题有很大的了解。

---- COMMENT PER FEEDBACK ---- ----意见反馈----

I would put your update within a try/catch, and step into the program to see what the exception is. 我会将您的更新放入try / catch,然后进入程序以查看异常是什么。 The message adn/or inner exception of the error might give more info. 错误消息和/或内部异常消息可能会提供更多信息。 However, try to simplify your UPDATE to only include a FEW fields with the WHERE "Key" element. 但是,请尝试简化UPDATE,使其仅在WHERE“ Key”元素中包含FEW字段。

Additionally, and I oopsed, missed this from first part answer. 另外,我还想过,从第一部分答案中错过了这一点。 You might have to identify the datatable's "PrimaryKey" column. 您可能必须识别数据表的“ PrimaryKey”列。 To do so, its a property of the DataTable that expects and array of columns that represent the primary key for the table. 为此,它是DataTable的一个属性,该属性期望和代表表主键的列数组。 What I did was... 我所做的是...

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

I would comment out your full update string and all its parameters for your UPDATE. 我会为您的UPDATE注释掉完整的更新字符串及其所有参数。 Then, build it with just as simple as my sample of only setting 2-3 columns and the where clause 然后,以仅设置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"

Pick fields like int or char so they have the least probability of problems for data type conversions, then, once that works, try adding all your "int" and "character" columns... then add any others. 选择int或char这样的字段,以便它们对数据类型转换的问题发生的可能性最小,然后,一旦可行,请尝试添加所有“ int”和“ character”列……然后添加其他任何列。 Also, which database are you going against. 另外,您要针对哪个数据库。 SOME databases don't use "?" 某些数据库不使用“?” as placeholder in the command but use "named" parameters, some using 作为命令中的占位符,但使用“命名”参数,有些使用

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

Hope this gets you over the hump... 希望这能使您度过难关...

You could use the String.Format Method to replace the @newVal1, @newVal2, ... in your code, like this da.UpdateCommand = new OleDbCommand(String.Format("UPDATE TABLE_NAME SET (COL1, COL2, ...) VALUES ({0}, {1}, ...) WHERE id=@id",OBJECT_ARRAY_CONTAINING_VALUES_FROM_THEDG)); 您可以使用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 per comment] [评论的开斋节]

To handle the row[0] , row[1] you need a loop like: 要处理row[0]row[1]您需要像这样的循环:

for(i=0; i<rows.Count; i++) {

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

da.Update(dt);

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM