更改类型化数据集的 TableAdapter 基类

页面创建日期 :

创建和生成类型化数据集的代码

类型化 DataSet 允许您创建基于 SQL 的每列类型信息的 DataTable,并使用 TableAdapter 简化与 DB 的数据交互。

由于此处不是创建类型化 DataSet 的目标,因此让我们快速创建 DataSet,而数据库和表是准备的。 您可以随意布局表。

首先,将 DataSet 作为新项目添加到项目中。 名字可以做任何事情,但在这里,它保持原样。

打开 DataSet 并从设计器添加 TableAdapter。

向导将生成 DataTable 和 TableAdapter。

使用您创建的 DataTable 和 TableAdapter 从数据库中检索和使用记录的示例可能如下所示: (这只是一个例子)

public Form1()
{
  InitializeComponent();

  using (var adapter = new 金額集計TestTableAdapter())
  {
    var table = adapter.GetData();

    foreach (var row in table)
    {
      Trace.WriteLine(string.Format("{0}:{1}", row.年月, row.金額));
    }
  }
}

通常,在使用此 DataSet 的项目中,只有一个表,并且创建许多包含表或多个表的数据集。 我认为,如果发生这种情况,我们想到的是处理的共性。 例如,您可以动态更改内部使用的 SQL 以更改记录检索条件。

但是,实际上,从 DataSet 创建的 TableAdapter 类是自动生成的代码。 此外,由于此 TableAdapter 类是组件类继承的,因此没有真正通用的方法或属性。 不能将基类传递给方法,并调用与 TableAdapter 相关的操作。

此外,内部使用的 SQL 和用于访问数据库的 SqlDataAdapter 等在受保护中声明,因此不能从外部触摸。

但是,您可以按照声明方式访问在受保护中声明的方法和属性,也可以创建继承 TableAdapter 类的类,并且此 TableAdapter 类具有部分修饰符,因此可以通过声明其他方法和属性来扩展处理。 您还可以创建新属性以获取内部属性,如以下代码所示:

using System.Data.SqlClient;
namespace DataSetBaseAdapter {
    public partial class DataSet1 {
    }
}

namespace DataSetBaseAdapter.DataSet1TableAdapters
{
  public partial class 金額集計TestTableAdapter
  {
    public SqlDataAdapter InnerAdapter
    {
      get { return Adapter; }
    }
  }
}

实际上,此 TableAdapter 允许您访问扩展的属性。

但是,由于可以访问内部属性,因此处理不是通用的,您仍必须为每个创建的 DataSet 编写代码。

更改 TableAdapter 基类

如前所述,TableAdapter 类继承了组件类,因此很难使处理变得通用。 如果更改类继承的代码部分,则代码是自动生成的,因此再次更新 DataSet 将返回代码。 如果可以,可以编写一个将接口继承到另一个文件的部件类,但这没有意义,因为您只需编写最终创建的 TableAdapter 的数量。

实际上,有一种机制可以更改此 TableAdapter 的继承类。 我想解释一下这个程序。

首先,创建要继承的类。 由于 TableAdapter 最初继承组件类,因此您创建的类也继承组件类。 现在,我们将编写一个要通用的代码,但让我们只创建一个类。 将命名空间与您创建的命名空间匹配。

using System.ComponentModel;

namespace DataSetBaseAdapter
{
  public class BaseAdapter : Component
  {
  }
}

然后,打开 DataSet 设计器并选择您创建的 TableAdapter。

右键单击以打开属性。 属性称为 BaseClass,最初应为 System.ComponentModel.Component。 将其重写为刚刚创建的类。 写所有内容,包括命名空间。

保存后,您将看到 TableAdapter 的基类已更改。 通过为每个 TableAdapter 设置此设置,可以将常见操作写入基类。

例如,如果要访问内部 SQL 或 SqlDataAdapter,请执行以下操作: 自动创建的适配器和 CommandCollection 是继承类创建的属性,不能直接从继承者处联系。 以下代码使用反射强制访问。

using System.ComponentModel;
using System.Data.SqlClient;
using System.Reflection;

namespace DataSetBaseAdapter
{
  public class BaseAdapter : Component
  {
    public SqlDataAdapter InnerAdapter
    {
      get
      {
        return (SqlDataAdapter)GetType().GetProperty("Adapter",
          BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this, null);
      }
    }

    public SqlCommand[] InnerCommandCollection
    {
      get
      {
        return (SqlCommand[])GetType().GetProperty("CommandCollection",
          BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this, null);
      }
    }
  }
}

您可以看到,实际上,您可以使用 TableAdapter 访问源类的属性。