如何: 在 Visual C#.net 中实现 DataSet JOIN 帮助器类

文章翻译 文章翻译
文章编号: 326080 - 查看本文应用于的产品
展开全部 | 关闭全部

本文内容

概要

本分步指南介绍了如何实现和使用 DataSetHelper 该类包含示例代码,从两个或多个相关 数据表 定义创建 数据表 对象,并将来自源 数据表 对象的排序和筛选的记录复制到目标 数据表 的方式。

若要执行此操作中,您将使用下面的公共方法:
  • CreateJoinTable
  • InsertJoinInto
  • SelectJoinInto
SelectJoinInto 方法调用 CreateJoinTableInsertJoinInto 方法。私有帮助器方法和数据成员还可以用于存储已分析的字段列表。

DataSetHelper 类包含 数据集 的成员变量。(可选),您可以向 数据集 成员变量分配一个现有的 数据集。如果该成员变量指向有效的 数据集CreateJoinTableSelectJoinInto 方法创建的任何 DataTable 对象添加到 数据集。在这两种情况下在方法调用返回对 DataTable 对象的引用。InsertJoinInto 方法要求一个现有的目标 数据表,并且不返回任何内容。

有关 数据集 对象的详细信息,请单击下面文章编号,以查看 Microsoft 知识库中相应的文章:
313485信息: ADO.NET 数据集、 DataView 和指南 DataViewManager

要求

下面的列表概述了建议的硬件、 软件、 网络的基础结构和所需的服务包:
  • Windows XP、 Windows 2000 或 Windows NT 4.0 Service Pack 6a
  • Microsoft Visual Studio.net
本文假定您熟悉下列主题:
  • visual C#.net 语法
  • ADO.NET 基础知识和语法

DataSetHelper 外壳程序类

该代码在此部分中的声明 DataSetHelper 的所有项目将方法和成员变量都添加到其中的外壳程序类。
  1. 启动 Visual Studio.net。
  2. 文件 菜单上指向 新建,然后单击 项目
  3. 新建项目 对话框中单击在 项目类型Visual C# 项目,然后单击 模板 下的 类库
  4. 名称 框中键入 DataSetHelper
  5. 类代码替换下面的代码:
    public class DataSetHelper
    {
        public DataSet ds;
    
        public DataSetHelper(ref DataSet DataSet)
        {
    	ds = DataSet;
        }
        public DataSetHelper()
        {
    	ds = null;
        }
    }
    					
    使用两个构造函数重载可以创建类的实例,使用或不使用有效的 数据集 的引用。为包含一个有效的 数据集 的引用类,DataTable 对象方法返回的也自动添加到 数据集

字段列表分析程序

本节包含字段列表分析程序的代码。使用已分析的结构,以便 CreateJoinTableInsertJoinInto 方法无需重新分析字段列表中。这些方法必须重新分析字段列表中,如果它们被称为从 SelectJoinInto 方法或从您自己的代码。已分析的字段列表和未解析的字段列表存储在 DataSetHelper 类的 私有 成员变量中。
  1. 在""节中创建 DataSetHelper 类中添加以下 专用 的类定义:
    private class FieldInfo
    {
        public string RelationName;
        public string FieldName;	//source table field name
        public string FieldAlias;	//destination table field name
        public string Aggregate;
    }
    					
    : 此类是常见 DataSetHelper 的其他文章,并包含一些本文未使用的字段。

  2. 将下面的 私有 成员变量添加到 数据集 声明后立即在类定义:
    private System.Collections.ArrayList m_FieldInfo; private string m_FieldList; 
    					
  3. 将下面的 私有 方法添加到类定义。此方法与其他 DataSetHelper 文章中使用的方法相同
    private void ParseFieldList(string FieldList, bool AllowRelation)
    {
        /*
         * This code parses FieldList into FieldInfo objects  and then 
         * adds them to the m_FieldInfo private member
         * 
         * FieldList systax:  [relationname.]fieldname[ alias], ...
        */ 
        if (m_FieldList == FieldList) return;
        m_FieldInfo = new System.Collections.ArrayList();
        m_FieldList = FieldList;
        FieldInfo Field; string[] FieldParts;
        string[] Fields=FieldList.Split(',');
        int i;
        for (i=0; i<=Fields.Length-1; i++)
        {
            Field=new FieldInfo();
            //parse FieldAlias
            FieldParts = Fields[i].Trim().Split(' ');
            switch (FieldParts.Length)
            {
                case 1:
                    //to be set at the end of the loop
                    break;
                case 2:
                    Field.FieldAlias=FieldParts[1];
                    break;
                default:
                    throw new Exception("Too many spaces in field definition: '" + Fields[i] + "'.");	                        
            }
            //parse FieldName and RelationName
            FieldParts = FieldParts[0].Split('.');
            switch (FieldParts.Length)
            {
                case 1: 
                    Field.FieldName=FieldParts[0];
                    break;
                case 2:
                    if (AllowRelation==false)
                        throw new Exception("Relation specifiers not permitted in field list: '" + Fields[i] + "'.");
                    Field.RelationName = FieldParts[0].Trim();
                    Field.FieldName=FieldParts[1].Trim();
                    break;
                default:
                    throw new Exception("Invalid field definition: " + Fields[i] + "'.");
            }
            if (Field.FieldAlias==null) 
                Field.FieldAlias = Field.FieldName;
            m_FieldInfo.Add (Field);
        }
    }
    					

CreateJoinTable 方法

此部分包含 CreateJoinTable 方法的代码。

下面是 CreateJoinTable 方法的调用约定:
dt = dsHelper.CreateJoinTable("TestTable", ds.Tables["Employees"],
    "FirstName FName,LastName LName,DepartmentEmployee.DepartmentName Department");
				
此调用示例创建一个 TableName TestTable 和三个字段 (FName、 LName,和部门) 的新 数据表。这三个域必须为该名字和雇员表中的姓氏字段和 DepartmentName 字段访问通过 DepartmentEmployee DataRelation 对象的父表中相同的数据类型。

若要指定字段在字段列表中使用以下语法:
[relationname.]fieldname[ alias], ...
				
注意此语法的以下:
  • ColumnName数据类型 属性都将被复制到目标 数据表 的唯一属性。
  • 计算的结果将包含表达式的字段的被复制。
  • 您可以通过指定一个别名的名称重命名目标 数据表 中的字段。
  • 字段列表可以包含字段名称中比源 数据表 中顺序不同的顺序列出的一个的子集。空白字段列表是否是引发异常。
  • DataRelation 必须与父表相关。例如对于如果要创建将在客户、 雇员,和订单表的字段组合在一起的表,您必须使用订单表作为源表,然后关系的方式引用该客户和雇员表中的字段。
若要调用 CreateJoinTable 方法,将下面的方法添加到""节中创建该 DataSetHelper 类:
public DataTable CreateJoinTable(string TableName, DataTable SourceTable, string FieldList)
{
    /*
     * Creates a table based on fields of another table and related parent tables
     * 
     * FieldList syntax: [relationname.]fieldname[ alias][,[relationname.]fieldname[ alias]]...
    */ 
    if (FieldList==null)
    {
        throw new ArgumentException("You must specify at least one field in the field list.");
        //return CreateTable(TableName, SourceTable);
    }
    else
    {
        DataTable dt = new DataTable(TableName);
        ParseFieldList(FieldList, true);
        foreach(FieldInfo Field in m_FieldInfo)
        {
            if(Field.RelationName==null)
            {
                DataColumn dc = SourceTable.Columns[Field.FieldName];
                dt.Columns.Add(dc.ColumnName, dc.DataType, dc.Expression);
            }
            else
            {
                DataColumn dc = SourceTable.ParentRelations[Field.RelationName].ParentTable.Columns[Field.FieldName];
                dt.Columns.Add(dc.ColumnName, dc.DataType, dc.Expression);
            }
        }
        if (ds!=null)
            ds.Tables.Add(dt);
        return dt;
    }
}
				

InsertJoinInto 方法

此部分包含 InsertJoinInto 方法的代码。InsertJoinInto 方法将复制的排序和筛选从源表和目标表与相关表记录。您在调用 ParseFieldList 属性时您可以分析以前已分析的列表,如果这些列表都可用。空白字段列表是否是引发异常。

下面是 InsertJoinInto 方法的调用约定:
dsHelper.InsertJoinInto(ds.Tables["TestTable"], ds.Tables["Employees"], 
    "FirstName FName,LastName LName,DepartmentEmployee.DepartmentName Department", 
    "EmployeeID<5", "BirthDate");
				
的调用示例复制 TestTable 数据表 中,雇员 数据表 (和相关 数据表 的 DepartmentName 字段) 从其上筛选记录"雇员 id < 5"并按出生日期。

: 筛选器和排序表达式只适用于源表而不到任何相关的表。

若要调用 InsertJoinInto 方法,将下面的方法添加到""节中创建该 DataSetHelper 类:
public void InsertJoinInto(DataTable DestTable, DataTable SourceTable, 
    string FieldList, string RowFilter, string Sort)
{
    /*
    * Copies the selected rows and columns from SourceTable and inserts them into DestTable
    * FieldList has same format as CreatejoinTable
    */ 
    if (FieldList==null)
    {
        throw new ArgumentException("You must specify at least one field in the field list.");
        //InsertInto(DestTable, SourceTable, RowFilter, Sort);
    }
    else
    {
    ParseFieldList(FieldList, true);
    DataRow[] Rows = SourceTable.Select(RowFilter, Sort);
    foreach(DataRow SourceRow in Rows)
    {
            DataRow DestRow = DestTable.NewRow();
            foreach(FieldInfo Field in m_FieldInfo)
            {
                if(Field.RelationName==null)
                {
                    DestRow[Field.FieldName] = SourceRow[Field.FieldName];
                }
                else
                {
                    DataRow ParentRow = SourceRow.GetParentRow(Field.RelationName);
                    DestRow[Field.FieldName] = ParentRow[Field.FieldName];
                }
            }
            DestTable.Rows.Add(DestRow);
        }
    }
}
				

SelectJoinInto 方法

此部分包含 SelectJoinInto 方法的代码。此方法是 CreateJoinTableInsertJoinInto 方法的组合。SelectJoinInto 方法创建基于现有 数据表 对象和 $ 副本记录进行排序和筛选到新 数据表 的新 数据表

下面是 SelectJoinInto 方法的调用约定:
dt = dsHelper.SelectInto("TestTable", ds.Tables["Employees"], 
    "FirstName FName,LastName LName,DepartmentEmployee.DepartmentName Department", "EmployeeID<5", "BirthDate");
				
该示例调用创建 数据表 名 TestTable 为具有三个字段。这三个域基于在名字和雇员 数据表 的姓氏字段和 数据表 引用通过 DepartmentEmployee DataRelation DepartmentName 字段。然后本示例将雇员 数据表 中的记录复制到 TestTable 数据表,筛选依据的"雇员 id < 5"并按出生日期。

: 筛选器和排序表达式只适用于源表而不到相关表。

若要调用 SelectJoinInto 方法,将下面的方法添加到""节中创建该 DataSetHelper 类:
public DataTable SelectJoinInto(string TableName, DataTable SourceTable, string FieldList, string RowFilter, string Sort)
{
    /*
     * Selects sorted, filtered values from one DataTable to another.
     * Allows you to specify relationname.fieldname in the FieldList to include fields from
     *  a parent table. The Sort and Filter only apply to the base table and not to related tables.
    */ 
    DataTable dt = CreateJoinTable(TableName, SourceTable, FieldList);
    InsertJoinInto(dt, SourceTable, FieldList, RowFilter, Sort);
    return dt;
}
				

测试应用程序

  1. 保存,然后编译 DataSetHelper 类在上一节中创建的。
  2. 请按照下列步骤创建一个新 Visual C# Windows 应用程序:
    1. 启动 Visual Studio.net。
    2. 文件 菜单上指向 新建,然后单击 项目
    3. 新建项目 对话框中单击在 项目类型Visual C# 项目,然后单击 模板 下的 Windows 应用程序
  3. 在解决方案资源管理器中,用鼠标右键单击该的解决方案,然后单击 添加现有项目。添加 DataSetHelper 项目。
  4. 项目 菜单上单击 添加引用
  5. 添加引用 对话框中单击 项目 选项卡,然后将对 DataSetHelper 项目的引用添加到 Windows 窗体应用程序。
  6. 在窗体设计器中有三个 按钮 控件和一个 DataGrid 控件从工具箱拖动到窗体。命名按钮 btnCreateJoinbtnInsertJoinIntobtnSelectJoinInto。使 DataGrid 控件 (dataGrid1) 的默认名称。
  7. 在窗体的代码将以下的 Using 语句添加到代码窗口的顶部:
    using System.Data;
    					
  8. 将下面的变量声明添加到窗体定义:
    DataSet ds; DataSetHelper.DataSetHelper dsHelper;
    					
  9. 将下面的代码添加到 Form_Load 事件:
    ds = new DataSet();
    dsHelper = new DataSetHelper.DataSetHelper(ref ds);
    //Create source tables
    DataTable dt = new DataTable("Employees");
    dt.Columns.Add("EmployeeID",Type.GetType("System.Int32") );
    dt.Columns.Add("FirstName", Type.GetType("System.String"));
    dt.Columns.Add("LastName", Type.GetType("System.String"));
    dt.Columns.Add("BirthDate", Type.GetType("System.DateTime"));
    dt.Columns.Add("JobTitle", Type.GetType("System.String"));
    dt.Columns.Add("DepartmentID", Type.GetType("System.Int32"));
    dt.Rows.Add(new object[] {1, "Tommy", "Hill", new DateTime(1970, 12, 31),  "Manager", 42});
    dt.Rows.Add(new object[] {2, "Brooke", "Sheals", new DateTime(1977, 12, 31), "Manager", 23});
    dt.Rows.Add(new object[] {3, "Bill", "Blast", new DateTime(1982, 5, 6), "Sales Clerk", 42});
    dt.Rows.Add(new object[] {1, "Kevin", "Kline", new DateTime(1978, 5, 13), "Sales Clerk", 42});
    dt.Rows.Add(new object[] {1, "Martha", "Seward", new DateTime(1976, 7, 4), "Sales Clerk", 23});
    dt.Rows.Add(new object[] {1, "Dora", "Smith", new DateTime(1985, 10, 22), "Trainee", 42});
    dt.Rows.Add(new object[] {1, "Elvis", "Pressman", new DateTime(1972, 11, 5), "Manager", 15});
    dt.Rows.Add(new object[] {1, "Johnny", "Cache", new DateTime(1984, 1, 23), "Sales Clerk", 15});
    dt.Rows.Add(new object[] {1, "Jean", "Hill", new DateTime(1979, 4, 14), "Sales Clerk", 42});
    dt.Rows.Add(new object[] {1, "Anna", "Smith", new DateTime(1985, 6, 26), "Trainee", 15});
    ds.Tables.Add(dt);
    
    dt = new DataTable("Departments");
    dt.Columns.Add("DepartmentID", Type.GetType("System.Int32"));
    dt.Columns.Add("DepartmentName", Type.GetType("System.String"));
    dt.Rows.Add(new object[] {15, "Men's Clothing"});
    dt.Rows.Add(new object[] {23, "Women's Clothing"});
    dt.Rows.Add(new object[] {42, "Children's Clothing"});
    ds.Tables.Add(dt);
    
    ds.Relations.Add("DepartmentEmployee",     ds.Tables["Departments"].Columns["DepartmentID"], 
        ds.Tables["Employees"].Columns["DepartmentID"]);
    					
  10. 将下面的代码添加到 btnCreateJoin_Click 事件:
    dsHelper.CreateJoinTable("EmpDept",ds.Tables["Employees"], 
        "FirstName FName,LastName LName,BirthDate,DepartmentEmployee.DepartmentName Department");
    dataGrid1.SetDataBinding(ds, "EmpDept");
    					
  11. 将下面的代码添加到 btnInsertJoinInto_Click 事件:
    dsHelper.InsertJoinInto(ds.Tables["EmpDept"], ds.Tables["Employees"], 
        "FirstName FName,LastName LName,BirthDate,DepartmentEmployee.DepartmentName Department",
        "JobTitle='Sales Clerk'", "DepartmentID");
    dataGrid1.SetDataBinding(ds, "EmpDept");
    					
  12. 将下面的代码添加到 btnSelectJoinInto_Click 事件:
    dsHelper.SelectJoinInto("EmpDept2", ds.Tables["Employees"],
        "FirstName,LastName,BirthDate BDate,DepartmentEmployee.DepartmentName Department", 
        "JobTitle='Manager'", "DepartmentID");
    dataGrid1.SetDataBinding(ds, "EmpDept2");
    					
  13. 运行在的应用程序,然后单击每个按钮。请注意 DataGrid 填入表和数据的代码。

    : 可以只单击 btnCreateJoinbtnSelectJoinInto 按钮一次。如果您单击这些按钮中的任何一个多个时间,您将收到一条错误消息,您试图添加同一个表两次。此外,单击 btnInsertJoinInto 之前,您必须单击 btnCreateJoin ; 否则,目标 数据表 不会创建。如果多次单击 btnInsertJoinInto 按钮,您填充 DataGrid 重复记录。

增强观点

  • ColumnName数据类型 属性都将被复制到目标 数据表 的唯一属性。您可以扩展 CreateTable 方法复制如 MaxLength 属性的其他属性,也可以创建新的键列。
  • 表达式 属性不会被复制 ; 而是,复制计算的结果。因此,您没有添加到目的表的表达式所引用的字段。此外,目标列可以在结果列表中任一否则依赖此列的列比前面出现。您可以修改 CreateTable 方法复制 (InsertInto 列忽略含有 表达式 的列) 表达式,虽然这是一种取决于该段落中前面提到的限制。
  • 您可以将 CreateJoinTableInsertJoinInto 中和 SelectJoinInto 方法的功能合并到 CreateTableInsertInto 中和 SelectInto 方法。有关 CreateTableInsertInto 中和 SelectInto 方法的其他信息请单击下面文章编号,以查看 Microsoft 知识库中相应的文章:
    326009HOWTO: 在 Visual C#.net 中实现 DataSet SELECT INTO 帮助器类
    如果要合并这些的方法,但如果在一个类中有两套方法,您可以启用 CreateJoinTableInsertJoinInto 方法来处理一个空的字段列表中,通过移除 引发 语句和 uncommenting CreateTableInsertInto 方法中下列代码行调用:
        if (FieldList==null)
        {
            throw new ArgumentException("You must specify at least one field in the field list.");
            //return CreateTable(TableName, SourceTable);
        }
    					
    -并且-
        if (FieldList==null)
        {
            throw new ArgumentException("You must specify at least one field in the field list.");
            //InsertInto(DestTable, SourceTable, RowFilter, Sort);
        }
    					

故障排除

  • 在 fieldname 和字段列表中的别名部分必须遵守 DataColumn 命名约定。语法分析器还限制了的名称,该名称不能包含句点 (.) 逗号 (,) 或空格 ()。
  • 如果不止一次单击一个按钮,同一个表将添加两次到 数据集,这将导致异常。要变通解决此问题,您可以将代码添加到测试应用程序中以检查是否已存在相同名称的 数据表。或者,您可以创建一个 数据集 的引用不 DataSetHelper 类,然后 DataGrid.DataSource 属性直接绑定到 dt 变量,而不是通过使用 SetDataBinding 方法调用。
  • 如果源表中使用自定义数据类型 (也就是类),必须将代码添加到该 InsertJoinInto 方法以执行数据的深层副本。否则,仅引用将被复制。

属性

文章编号: 326080 - 最后修改: 2003年9月3日 - 修订: 2.3
这篇文章中的信息适用于:
  • Microsoft ADO.NET 1.1
  • Microsoft ADO.NET 1.0
  • Microsoft Visual C# .NET 2003 标准版
  • Microsoft Visual C# .NET 2002 标准版
关键字:?
kbmt kbhowtomaster kbsystemdata KB326080 KbMtzh
机器翻译
注意:这篇文章是由无人工介入的微软自动的机器翻译软件翻译完成。微软很高兴能同时提供给您由人工翻译的和由机器翻译的文章, 以使您能使用您的语言访问所有的知识库文章。然而由机器翻译的文章并不总是完美的。它可能存在词汇,语法或文法的问题,就像是一个外国人在说中文时总是可能犯这样的错误。虽然我们经常升级机器翻译软件以提高翻译质量,但是我们不保证机器翻译的正确度,也不对由于内容的误译或者客户对它的错误使用所引起的任何直接的, 或间接的可能的问题负责。
点击这里察看该文章的英文版: 326080
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。

提供反馈

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com