語言

驗證 .NET Framework 應用程式中數據集中的數據

備註

類別 DataSet 和相關類別是 2000 年代初的舊版 .NET Framework 技術,可讓應用程式在應用程式與資料庫中斷連線時使用記憶體中的數據。 這些技術特別適用於可讓使用者修改數據並將變更保存回資料庫的應用程式。 雖然數據集是經過證實的成功技術,但新 .NET 應用程式的建議方法是使用 Entity Framework Core。 Entity Framework 提供更自然的方式,以表格式數據作為物件模型使用,而且具有更簡單的程序設計介面。

驗證數據是確認數據對象中輸入的值符合數據集架構內的條件約束的程式。 驗證程式也會確認這些值遵循為您的應用程式建立的規則。 在將更新傳送至基礎資料庫之前,最好先驗證數據。 這可減少錯誤,以及應用程式與資料庫之間可能的往返次數。

您可以藉由對數據集本身建置驗證檢查,確認寫入數據集的數據是有效的。 不論更新的執行方式為何,數據集都可以檢查數據,無論是透過表單、元件內的控件,還是以其他方式直接執行。 因為數據集是應用程式的一部分(不同於資料庫後端),所以它是建置應用程式特定驗證的邏輯位置。

將驗證新增至應用程式的最佳位置是在數據集的部分類別檔案中。 在 Visual Basic 或 Visual C# 中,開啟 資料集設計工具 ,然後按兩下您要建立驗證的資料行或資料表。 此動作會開啟程式代碼檔案,您可以在其中建立 ColumnChanging 或 RowChanging 事件處理程式。

private static void OnColumnChanging(object sender, DataColumnChangeEventArgs e)
{

}

驗證數據

資料集內的驗證是以下列方式完成:

當記錄中的變更發生時,DataTable 物件會引發數個事件:

  • ColumnChanging 和 ColumnChanged 事件會在每次修改個別欄位的過程中及完成後被引發。 當您想要驗證特定資料行中的變更時,此 ColumnChanging 事件很有用。 建議變更的相關信息會作為參數隨事件傳遞。
  • RowChanging 和 RowChanged 事件會在數據列中的任何變更期間和之後被觸發。 事件 RowChanging 較為一般。 它表示變更發生在數據列中某處,但您不知道哪一個數據行已經變更。

根據預設,數據行的每個變更都會引發四個事件。 第一個是針對正在變更的特定欄的ColumnChanging和ColumnChanged事件。 接下來是 RowChanging 和 RowChanged 事件。 如果要對數據列進行多個變更,則會針對每個變更引發事件。

備註

數據列的 BeginEdit 方法會在每個個別數據行變更之後關閉 RowChanging 和 RowChanged 事件。 在此情況下,直到呼叫EndEdit方法時,才會引發事件,而RowChanging和RowChanged事件只引發一次。 如需詳細資訊,請參閱 在填滿數據集時關閉條件約束。

您選擇的事件取決於您想要驗證的細微程度。 如果請務必在數據行變更時立即攔截錯誤,請使用 ColumnChanging 事件來建置驗證。 否則,請使用 RowChanging 事件,這可能會一次捕捉到數個錯誤。 此外,如果您的資料已結構化,以便根據另一個欄位的內容來驗證一個欄位的值,請在 RowChanging 事件期間執行驗證。

更新記錄時,DataTable 物件會引發事件,您可以在變更發生時以及變更完成後進行回應。

如果您的應用程式使用型別化資料集,您可以建立強型別事件處理程式。 這會新增四個具型別的額外事件,您可以建立處理程式:dataTableNameRowChanging、dataTableNameRowChanged、dataTableNameRowDeleting 和 dataTableNameRowDeleted。 這些具類型的事件處理程式會傳遞自變數,其中包含數據表的數據行名稱,讓程式代碼更容易撰寫和讀取。

數據更新事件

事件 說明
ColumnChanging 正在變更數據列中的值。 事件會將數據列和數據行傳遞至您,以及建議的新值。
ColumnChanged 數據行中的值已變更。 事件會將數據行和數據列,連同預設值傳遞給您。
RowChanging 對 DataRow 物件所做的變更即將提交回資料集。 如果您尚未呼叫 BeginEdit 方法,當 ColumnChanging 事件引發後,RowChanging 會立即針對每一個變更的數據行引發事件。 如果您在進行變更之前呼叫 BeginEdit , RowChanging 只有在呼叫 EndEdit 方法時,才會引發 事件。

事件會將資料列傳遞給您,還會包含一個值來指示正在執行的動作類型(例如變更、插入等等)。
RowChanged 數據列已變更。 事件會將資料列傳遞給您,並指出正在執行動作類型的值(修改、插入等等)。
RowDeleting 正在刪除數據列。 事件會將資料列與顯示動作類型(刪除)的值一同傳遞給您。
RowDeleted 一個資料列已被刪除。 事件將資料列與一個值傳遞給您,指出正在執行的操作類型為刪除。

在更新過程中,ColumnChanging、RowChanging 和 RowDeleting 這些事件會被引發。 您可以使用這些事件來驗證資料或執行其他類型的處理。 由於更新在這些事件期間進行中,您可以透過拋出例外狀況來取消更新,從而防止更新完成。

ColumnChanged RowChanged和 RowDeleted 事件是更新成功完成時所引發的通知事件。 當您想要根據成功的更新採取進一步的動作時,這些事件很有用。

在數據行變更期間驗證數據

備註

數據集設計工具會建立部分類別,其中驗證邏輯可以新增至數據集。 設計工具產生的數據集不會刪除或變更部分類別中的任何程序代碼。

您可以藉由回應 ColumnChanging 事件,在數據行中的值變更時驗證數據。 引發時,這個事件會傳遞包含當前欄建議值的事件參數(ProposedValue)。 根據 e.ProposedValue 的內容,您可以:

  • 不執行任何動作來接受建議的值。

  • 從數據行變更事件處理程式內設定數據行錯誤 (SetColumnError) 來拒絕建議的值。

  • 選擇性地使用 ErrorProvider 控制項向使用者顯示錯誤訊息。 如需詳細資訊,請參閱 ErrorProvider 元件。

驗證也可以在 RowChanging 事件期間執行。

在數據列變更期間驗證數據

您可以撰寫程式代碼來確認您要驗證的每個資料列都包含符合應用程式需求的數據。 若要這樣做,請設定數據行,以指出如果建議的值無法接受,它就會包含錯誤。 下列範例會在 Quantity 欄的值為 0 或更少時設定欄錯誤。 數據列變更事件處理程式應該類似下列範例。

在資料列變更時驗證資料 (Visual Basic)

  1. 在 數據集設計工具中開啟您的數據集。 如需詳細資訊,請參閱 逐步解說:在數據集設計工具中建立數據集。

  2. 按兩下您要驗證之資料表的標題列。 此動作會在數據集的部分類別檔案中自動建立 DataTable 的 RowChanging 事件處理程式。

    小提示

    按兩下資料表名稱左側,以建立資料列變更事件處理程式。 如果您按兩下資料表名稱,您可以編輯它。

    Private Sub Order_DetailsDataTable_Order_DetailsRowChanging(
        ByVal sender As System.Object, 
        ByVal e As Order_DetailsRowChangeEvent
      ) Handles Me.Order_DetailsRowChanging
    
        If CType(e.Row.Quantity, Short) <= 0 Then
            e.Row.SetColumnError("Quantity", "Quantity must be greater than 0")
        Else
            e.Row.SetColumnError("Quantity", "")
        End If
    End Sub
    

在資料列變更時驗證資料 (C#)

  1. 在 數據集設計工具中開啟您的數據集。 如需詳細資訊,請參閱 逐步解說:在數據集設計工具中建立數據集。

  2. 按兩下您要驗證之資料表的標題列。 此動作會為 DataTable 建立部分類別檔案。

    備註

    數據集設計工具不會自動建立RowChanging事件的事件處理程式。 您必須建立方法來處理 RowChanging 事件,並執行程式碼來連結數據表初始化方法中的事件。

  3. 將下列程式代碼複製到部分類別:

    public override void EndInit()
    {
        base.EndInit();
        Order_DetailsRowChanging += TestRowChangeEvent;
    }
    
    public void TestRowChangeEvent(object sender, Order_DetailsRowChangeEvent e)
    {
        if ((short)e.Row.Quantity <= 0)
        {
            e.Row.SetColumnError("Quantity", "Quantity must be greater than 0");
        }
        else
        {
            e.Row.SetColumnError("Quantity", "");
        }
    }
    

擷取已變更的數據列

數據表中的每個數據列都有屬性 RowState ,可使用 列舉中的 DataRowState 值來追蹤該數據列的目前狀態。 您可以透過呼叫GetChanges、DataSet或DataTable的方法,從數據集或數據表中傳回已變更的行。 您可以通過先調用數據集的HasChanges方法,確認變更是否存在,然後再調用GetChanges。

備註

將變更提交至資料集或資料表後(透過呼叫 AcceptChanges 方法),GetChanges 方法不會返回任何資料。 如果您的應用程式需要處理變更的數據列,您必須先處理變更,才能呼叫 AcceptChanges 方法。

GetChanges呼叫數據集或數據表的 方法會傳回只包含已變更記錄的新數據集或數據表。 如果您想要取得特定記錄,例如,只有新記錄或只修改過的記錄,您可以將列舉中的值 DataRowState 當做參數傳遞至 GetChanges 方法。

DataRowVersion使用 列舉來存取數據列的不同版本(例如,處理數據列之前的數據列的原始值)。

從數據集取得所有已變更的記錄

  • 調用數據集的GetChanges方法。

    下列範例會建立名為 changedRecords 的新數據集,並將所有已變更的記錄填入名為 dataSet1的另一個數據集。

    DataSet changedRecords = dataSet1.GetChanges();
    

從數據表取得所有已變更的記錄

  • 調用 DataTable 的GetChanges方法。

    下列範例會建立名為 changedRecordsTable 的新數據表,並將所有已變更的記錄填入名為 dataTable1的另一個數據表。

    DataTable changedRecordsTable = dataTable1.GetChanges();
    

取得具有特定數據列狀態的所有記錄

  • GetChanges呼叫數據集或數據表的 方法,並將列舉值當做自變數傳遞DataRowState。

    下列範例示範如何建立名為 addedRecords 的新數據集,並只填入已新增至數據集的 dataSet1 記錄。

    DataSet addedRecords = dataSet1.GetChanges(DataRowState.Added);
    

    下列範例示範如何傳回最近新增至 Customers 數據表的所有記錄:

    private NorthwindDataSet.CustomersDataTable GetNewRecords()
    {
        return (NorthwindDataSet.CustomersDataTable)
            northwindDataSet1.Customers.GetChanges(DataRowState.Added);
    }
    

存取 DataRow 的原始版本

對數據列進行變更時,數據集會保留數據列的原始 (Original) 和新版本Current。 例如,在呼叫 AcceptChanges 方法之前,您的應用程式可以存取不同版本的記錄(如 列舉中所 DataRowVersion 定義),並據以處理變更。

備註

只有在編輯行之後且呼叫AcceptChanges方法之前,才會存在不同的行版本。 呼叫AcceptChanges方法之後,原始版本和目前版本相同。

傳遞 DataRowVersion 值以及數據行索引(或數據行名稱做為字串)會從該數據行的特定數據列版本傳回值。 在ColumnChanging 和ColumnChanged 事件期間,會識別已變更的數據行。 這是檢查不同數據列版本以進行驗證的好時機。 不過,如果您暫時暫停限制,則不會引發這些事件,您必須以程式碼方式識別哪些欄位已變更。 您可以逐一查看 Columns 集合並比較不同的 DataRowVersion 值來執行此動作。

取得記錄的原始版本

  • 傳入您要傳回之資料列的 DataRowVersion,以存取資料行的值。

    下列範例示範如何使用DataRowVersion來取得DataRow中的CompanyName欄位的原始值:

    string originalCompanyName;
    originalCompanyName = northwindDataSet1.Customers[0]
        ["CompanyName", DataRowVersion.Original].ToString();
    

存取 DataRow 的目前版本

取得記錄的目前版本

  • 存取數據行的值,然後將參數新增至索引,指出您要傳回的數據列版本。

    下列範例示範如何使用 DataRowVersion 值來取得 中DataRow欄位的CompanyName目前值:

    string currentCompanyName;
    currentCompanyName = northwindDataSet1.Customers[0]
        ["CompanyName", DataRowVersion.Current].ToString();