【问题标题】:Using OleDbDataAdapter to update a DataTable C#使用 OleDbDataAdapter 更新 DataTable C#
【发布时间】:2012-04-27 19:23:28
【问题描述】:

我一直在尝试使用 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....)?

非常感谢!

【问题讨论】:

    标签: c# datatable dataadapter oledbdataadapter updatecommand


    【解决方案1】:

    数据适配器可以与数据表一起工作。因此,我实际上已经将我的组合成一个类并且工作得很好。除了我的东西的复杂性之外,这里有一个可以帮助你的 sn-p。添加参数时,您可以从 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 中,然后进入程序查看异常是什么。错误的消息和/或内部异常可能会提供更多信息。但是,请尝试简化您的 UPDATE 以仅包含带有 WHERE "Key" 元素的几个字段。

    另外,我很遗憾,从第一部分答案中错过了这个。您可能必须识别数据表的“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"
    

    希望这能让你度过难关...

    【讨论】:

    • 谢谢。我在执行 Update 方法时仍然遇到问题。它说我缺少一个参数的值。问题是否可能是我没有使用数据集? (我只是使用 DataTable 并使用 BindingSource 对象将其绑定到 DataGridView)。谢谢(:
    • @gavra,查看扩展答案,让我知道。
    • 非常感谢!这次的问题是我试图更新一个主键列。现在它工作得很好,我会包装它并在我的项目中使用它。祝你有美好的一天!
    【解决方案2】:

    您可以使用String.Format Method 替换代码中的@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<rows.Count; i++) {

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

        da.Update(dt);

    }

    【讨论】:

    • 感谢您的回复。我知道这种方法。问题在于更新数据表中的所有行,而我只有一个更新命令。例如,我可能想将 rows[0].myColumn 用作参数,然后该参数需要为 rows[1].myColumn。我还注意到有一种方法可以在不定义更新命令的情况下进行更新。只是还没弄清楚怎么做。
    • 您看过 Microsoft 的 DataAdapter.Update 文档吗?
    猜你喜欢
    • 1970-01-01
    • 2011-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-12
    • 2021-09-30
    • 1970-01-01
    相关资源
    最近更新 更多