【问题标题】:ADO.Net retrieving autoincrement values for MS Access database in strongly typed DataSetsADO.Net 在强类型数据集中检索 MS Access 数据库的自动增量值
【发布时间】:2018-01-15 18:36:13
【问题描述】:

我在 C# 中使用 MS Access 作为数据库服务器编写了一个数据库客户端应用程序。

用户使用DataGridView 插入新行。我需要在

上检索插入行的自动增量值
this.MyTableTableAdapter.Update(MyDataSet.MyTable)

操作。

我不能用

this.MyTableTableAdapter.Fill(MyDataSet.MyTable); 

更新操作后刷新整个表,因为需要插入记录的位置丢失了。

所以我读了docs.microsoft.com,“检索身份或自动编号值”部分:

https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/retrieving-identity-or-autonumber-values

了解如何去做。

他们写了一个模糊的描述:

某些数据库引擎,例如 Microsoft Access Jet 数据库引擎,不支持输出参数并且不能在一个批处理中处理多个语句。使用 Jet 数据库引擎时,您可以通过在 DataAdapter 的 RowUpdated 事件的事件处理程序中执行单独的 SELECT 命令来检索为插入的行生成的新自动编号值。

我还发现了一个必须在事件中执行的代码

https://www.safaribooksonline.com/library/view/adonet-cookbook/0596004397/ch04s04.html

private void OnRowUpdated(object Sender, OleDbRowUpdatedEventArgs args)
{
    // Retrieve autonumber value for inserts only.
    if(args.StatementType == StatementType.Insert)
    {
        // SQL command to retrieve the identity value created
        OleDbCommand cmd = new OleDbCommand("SELECT @@IDENTITY", da.SelectCommand.Connection);

        // Store the new identity value to the CategoryID in the table.
        args.Row[CATEGORYID_FIELD] = (int)cmd.ExecuteScalar( );
    }
}

问题在于 VS IDE 设计器创建了强类型的 DataSet,而没有 DataAdapter 对象的外部可见性。

它创建的 TableAdapter 是从 Component 继承的,而不是从 DataAdapter 继承的。

虽然它在 myTableTableAdapter 类中创建了一个真正的 DataAdapter,但它具有保护级别。

protected internal global::System.Data.OleDb.OleDbDataAdapter Adapter

所以我不能在 myTableTableAdapter 类之外向 Adapter 添加任何事件。

我假设代码应该写在 myTableTableAdapter 类中 但是这个类的代码是自动生成的,文件有下一条注释

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.42000
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

所以如果我添加任何更改,我的自定义代码可能会丢失。

所以我的问题是 - 如何在强类型数据集中为 DataAdapter 添加 RowUpdated 事件?

【问题讨论】:

  • 它是protected internal,表示protectedinternal。您应该能够访问 internal 字段,只要它与您尝试从中访问的代码位于同一项目(程序集)中
  • 是的。 myTable.Adapter.RowUpdated += OnRowUpdated;作品。谢谢。
  • 通常自动生成的代码是在 partial 类中完成的。如果是这种情况,您可以在另一个文件中添加相关代码,但它仍然在同一个类中。我不知道这里是否是这种情况。但如果是这样,那可能是更好的方法。
  • 是的。有两个文件:MyDataSet.Designer.cs 和 MyDataSet.cs 我可以在 MyDataSet.cs public partial class MyTableTableAdapter 中编写代码: global::System.ComponentModel.Component { private void MyMethod() { Adapter.RowUpdated += OnUserRowUpdated;但是如何(从哪里)使 MyMethod() 被调用? private void InitAdapter() { 在 MyDataSet.Designer.cs 文件中。

标签: c# ms-access ado.net auto-increment


【解决方案1】:

“由 Typed DataSet 创建的 DataSet、DataTables 和 DataRow 对象可以通过使用部分类进行扩展。”

有关部分类的更多信息,请参见此处的“第 3 步”:https://docs.microsoft.com/en-us/aspnet/web-forms/overview/data-access/introduction/creating-a-business-logic-layer-vb#step-3-adding-field-level-validation-to-the-datarow-classes

上面的例子使用了 ColumnChanging,但我相信你可以扩展 RowUpdated。

【讨论】:

  • 您好,我无法使用您的建议。 DataTable.BeginInit() 是虚拟的,它很好,但是,RowUpdated 是 OleDbDataAdapter 的一个事件,但我无法从 DataTable.BeginInit 方法内部访问 Adapter。
  • 有class public partial class myTableTableAdapter : global::System.ComponentModel.Component { protected internal global::System.Data.OleDb.OleDbDataAdapter Adapter { } } 它是类中的Adapter属性驻留并且 Adapter.RowUpdated 事件可用。但是 myTableTableAdapter 没有 BeginInit() 方法或任何其他适合使用的虚拟方法。
  • 在正常情况下需要在myTableTableAdapter类的构造函数中写入,但是在自动生成的文件——MyDataSet.Designer.cs中已经描述了构造函数。所以我不能在 MyDataSet.cs 中编写另一个构造函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 2017-08-17
  • 1970-01-01
相关资源
最近更新 更多