如何: 在 Visual C#.NET 中實作資料集加入協助程式類別

文章翻譯 文章翻譯
文章編號: 326080 - 檢視此文章適用的產品。
全部展開 | 全部摺疊

在此頁中

結論

本文將逐步告訴您,如何實作及使用 DataSetHelper 類別,其中包含從兩個或多個相關的 資料表 定義建立一個 DataTable 物件,並將排序和篩選的記錄從來源 DataTable 物件複製到目的地 DataTable 的範例程式碼的方式。

如果要執行此動作,您會使用下列的公用方法:
  • CreateJoinTable
  • InsertJoinInto
  • SelectJoinInto
SelectJoinInto 方法呼叫 CreateJoinTableInsertJoinInto 方法。您也可以使用私用 Helper 方法和資料成員來儲存已剖析的欄位清單。

DataSetHelper 類別包括 資料集 成員變數。選擇性地,您可以將現有的 資料集 指派給 資料集 成員變數。如果成員變數指向有效的 資料集CreateJoinTableSelectJoinInto 方法會建立任何 DataTable 物件會加入至 資料集。不論是哪一種方法呼叫會傳回 DataTable 物件的參考。InsertJoinInto 方法需要現有的目標 DataTable,且沒有傳回任何項目。

如需有關 資料集 物件的詳細資訊,按一下 [下面的文件編號,檢視 「 Microsoft 知識庫 」 中的發行項]:
313485ADO.NET 資料集、 DataView,和 DataViewManager 資訊: 藍圖

需求

下列清單列出建議的硬體、 軟體、 網路基礎結構及所需的 Service Pack:
  • Microsoft 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");
				
這個呼叫範例建立新的 資料表 具有 TestTable 和 (FName、 LName 和部門) 的三個欄位的 表格名稱。這些三個欄位有相同的資料類型為 「 名字在前] 和 [員工] 表格中的 [姓氏] 欄位及 DepartmentEmployee DataRelation 物件透過存取父資料表中的 [DepartmentName] 欄位。

使用下列的語法來指定欄位在欄位清單:
[relationname.]fieldname[ alias], ...
				
請注意下列的這種語法:
  • ColumnName資料類型] 屬性是唯一會複製到目的 資料表 的屬性。
  • 評估的結果就會複製對於包含運算式的欄位。
  • 您可以藉由指定一個別名名稱重新命名目的地 DataTable 中的欄位。
  • 欄位清單可以包含不同的順序比來源 DataTable 中順序中所列的欄位名稱的子集。如果欄位清單是空白的就會擲回例外狀況。
  • 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");
				
的呼叫範例複製記錄的員工 DataTable (和相關的 資料表 中的 [DepartmentName] 欄位) 到 TestTable DataTable 中,依篩選 「 員工編號 < 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 方法會建立新 DataTable 現有 DataTable 物件和副本記錄會排序和篩選到新的 資料表 為基礎。

下列是 SelectJoinInto 方法的呼叫慣例:
dt = dsHelper.SelectInto("TestTable", ds.Tables["Employees"], 
    "FirstName FName,LastName LName,DepartmentEmployee.DepartmentName Department", "EmployeeID<5", "BirthDate");
				
這個範例呼叫會建立三個欄位以命名 TestTable DataTable。這些三個欄位是以 [名字] 和 [員工 資料表 的 [姓氏] 欄位及經由 DepartmentEmployee DataRelation 參考 DataTable] 的 [DepartmentName] 欄位為基礎。然後此範例將員工 DataTable 複製記錄到 TestTable DataTable,依篩選的 「 員工編號 < 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 Form 應用程式]。
  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 按鈕一次。如果您一次以上按一下這些按鈕其中您會收到錯誤訊息您嘗試加入同一資料表兩次。此外,您必須先按一下 btnCreateJoin,再按一下 btnInsertJoinInto ; 否則目的地 DataTable 不會建立。如果您按一下 btnInsertJoinInto 按鈕多次,您填入 DataGrid 包含重複記錄的資料。

增強點子

  • ColumnName資料類型] 屬性是唯一會複製到目的 資料表 的屬性。您可以擴充 CreateTable 方法,以能夠複製如 MaxLength] 屬性的其他屬性,或者您也可以建立新的索引鍵資料行。
  • 運算式 屬性不會複製 ; 而,評估的結果就會複製。因此,您沒有新增到目的資料表運算式所參考的欄位。此外,目的資料行可以更早版本比這個資料行否則取決於資料行的任何結果清單中出現。您可以修改 CreateTable 方法來複製 運算式 (InsertInto 欄會忽略 運算式 的資料行),雖然這是受限於這個段落中稍早所述的限制。
  • 您可以將 CreateJoinTableInsertJoinIntoSelectJoinInto 方法的功能合併到 CreateTableInsertIntoSelectInto 方法。取得更多資訊有關 CreateTableInsertIntoSelectInto 的方法按一下面的文件編號,檢視 「 Microsoft 知識庫 」 中的發行項:
    326009HOWTO: 在 Visual C#.NET 中實作協助 DataSet SELECT INTO 程式類別
    如果不想合併這些方法,但如果您在單一類別中有兩組方法,您可以啟用 CreateJoinTableInsertJoinInto 方法,來處理空的欄位清單中,藉由移除 Throw 陳述式以及 uncommenting CreateTable 和下列幾行程式碼中的 InsertInto 方法的呼叫:
        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);
        }
    					

疑難排解

  • 欄位] 和 [欄位清單的別名部分必須遵守 DataColumn 命名慣例。剖析器也將限制之名稱,因為名稱不能包含句號 (.) 逗號 (,) 或空格 ()。
  • 如果按了按鈕一次以上,相同的資料表會新增兩次到 DataSet,這會產生例外狀況。如果要解決這個問題,您可以將程式碼加入至測試應用程式中,以檢查是否相同名稱的 資料表 已經存在。或者,您可以建立 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 Standard Edition
關鍵字:?
kbmt kbhowtomaster kbsystemdata KB326080 KbMtzh
機器翻譯
重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本: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