變更類型化資料集的 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 訪問來源類的屬性。