更改类型化数据集的 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 访问源类的属性。