在 .NET Framework 應用程式中驗證資料集中的資料
注意
資料集和相關類別是 2000 年代初的舊版 .NET Framework 技術,可讓應用程式在應用程式與資料庫中斷連線時使用記憶體中的資料。 這些技術特別適用於可讓使用者修改資料並將變更保存回資料庫的應用程式。 雖然已證明資料集是非常成功的技術,但建議新的 .NET 應用程式使用 Entity Framework Core。 Entity Framework 提供更自然的方式,將表格式資料作為物件模型使用,而且具有更簡單的程式設計介面。
驗證資料是確認輸入資料物件中的值符合資料集結構描述內條件約束的程序。 驗證程序也會確認這些值遵循為您的應用程式建立的規則。 在將更新傳送至基礎資料庫之前,最好先驗證資料。 這會減少錯誤以及應用程式與資料庫之間的可能往返次數。
您可以藉由對資料集本身建置驗證檢查,確認寫入資料集的資料是有效的。 不論更新的執行方式為何,資料集都可以檢查資料,無論是透過表單中的控制項、元件內,還是以其他方式直接執行。 因為資料集是應用程式的一部分 (與資料庫後端不同),它是建置應用程式特定驗證的邏輯位置。
將驗證新增至應用程式的最佳位置是在資料集的部分類別檔案中。 在 Visual Basic 或 Visual C# 中,開啟 DataSet 設計工具,然後按兩下您要建立驗證的資料行或資料表。 此動作會開啟程式碼檔案,您可以在其中建立 ColumnChanging 或 RowChanging 事件處理常式。
驗證資料
資料集內的驗證是以下列方式完成:
藉由建立可在變更期間檢查個別資料行中值的您自己的應用程式特定驗證。 如需詳細資訊,請參閱如何:在資料行變更期間驗證資料。
藉由建立可在整個資料列變更時檢查值資料的您自己的應用程式特定驗證。 如需詳細資訊,請參閱如何:在資料列變更期間驗證資料。
藉由建立索引鍵、唯一條件約束等,作為資料集實際結構描述定義的一部分。
藉由設定 DataColumn 物件的屬性,例如 MaxLength、AllowDBNull 和 Unique。
在記錄中發生變更時,DataTable 物件會引發數個事件:
- ColumnChanging 和 ColumnChanged 事件會在每次變更個別資料行期間和之後引發。 想要驗證特定資料行中的變更時,ColumnChanging 事件很有用。 提議的變更的相關資訊會以引數的形式隨著事件傳遞。
- RowChanging 和 RowChanged 事件會在資料列中的任何變更期間和之後引發。 RowChanging 事件較為一般。 它會指出在資料列中某處發生變更,但您不知道哪一個資料行已變更。
依預設,對資料行的每個變更都會因此引發四個事件。 首先是正在變更的特定資料行的 ColumnChanging 和 ColumnChanged 事件。 接下來是 RowChanging 和 RowChanged 事件。 如果要對資料列進行多個變更,則會針對每個變更引發事件。
注意
資料列的 BeginEdit 方法會在每個個別資料行變更之後關閉 RowChanging 和 RowChanged 事件。 在該情況下,只引發 RowChanging 和 RowChanged 事件一次時,在呼叫 EndEdit 方法之前,不會引發事件。 如需詳細資訊,請參閱在填滿資料集時關閉條件約束。
您選擇的事件取決於您想要驗證的細微程度。 如果在資料行變更時立即攔截錯誤很重要,請使用 ColumnChanging 事件來建置驗證。 否則,請使用 RowChanging 事件,其可能會導致一次攔截數個錯誤。 此外,如果您的資料已結構化,以便根據另一個資料行的內容來驗證一個資料行的值,請在 RowChanging 事件期間執行您的驗證。
更新記錄時,DataTable 物件會引發事件,您可以在變更發生時以及進行變更之後回應。
如果您的應用程式使用具類型的資料集,您可以建立強類型事件處理常式。 這會新增四個額外的具類型事件,您可以為其建立處理常式:dataTableNameRowChanging
、dataTableNameRowChanged
、dataTableNameRowDeleting
和 dataTableNameRowDeleted
。 這些具類型的事件處理常式會傳遞引數,其中包含資料表的資料行名稱,讓程式碼更容易撰寫和讀取。
資料更新事件
活動 | 描述 |
---|---|
ColumnChanging | 資料行中的值正在變更。 事件會將資料列和資料行,以及提議的新值傳遞給您。 |
ColumnChanged | 資料行中的值已變更。 事件會將資料列和資料行,以及提議的值傳遞給您。 |
RowChanging | 對 DataRow 物件所做的變更即將認可回資料集。 如果您尚未呼叫 BeginEdit 方法,則會在引發 ColumnChanging 事件之後,立即針對對每一個資料行的變更引發 RowChanging 事件。 如果您在進行變更之前呼叫 BeginEdit,只有在呼叫 EndEdit 方法時,才會引發 RowChanging 事件。 事件會將資料列以及一個值傳遞給您,指出正在執行什麼類型的動作 (變更、插入等)。 |
RowChanged | 資料列已變更。 事件會將資料列以及一個值傳遞給您,指出正在執行什麼類型的動作 (變更、插入等)。 |
RowDeleting | 正在刪除資料列。 事件會將資料列以及一個值傳遞給您,指出正在執行什麼類型的動作 (刪除)。 |
RowDeleted | 已刪除資料列。 事件會將資料列以及一個值傳遞給您,指出正在執行什麼類型的動作 (刪除)。 |
更新程序期間會引發 ColumnChanging、RowChanging 和 RowDeleting 事件。 您可以使用這些事件來驗證資料或執行其他類型的處理。 由於更新在這些事件期間進行中,因此您可以擲回例外狀況來取消更新,其會防止更新完成。
ColumnChanged、RowChanged 和 RowDeleted 事件是更新成功完成時引發的通知事件。 當您想要根據成功的更新採取進一步的動作時,這些事件很有用。
在資料行變更期間驗證資料
注意
DataSet 設計工具會建立部分類別,其中的驗證邏輯可以新增至資料集。 設計工具產生的資料集不會刪除或變更部分類別中的任何程式碼。
您可以藉由回應 ColumnChanging 事件,以在資料行中的值變更時驗證資料。 引發時,此事件會傳遞事件引數 (ProposedValue),其包含針對目前資料行提議的值。 根據 e.ProposedValue
的內容,您可以:
接受提議的值而不執行任何動作。
拒絕提議的值,從資料行變更事件處理常式內設定資料行錯誤 (SetColumnError)。
選擇性地使用 ErrorProvider 控制項向使用者顯示錯誤訊息。 如需詳細資訊,請參閱 ErrorProvider 元件。
驗證也可以在 RowChanging 事件期間執行。
在資料列變更期間驗證資料
您可以撰寫程式碼來驗證您想要驗證的每個資料行都包含符合應用程式需求的資料。 若要這樣做,請設定資料行,以指出如果提議的值無法接受,它就會包含錯誤。 下列範例會在 Quantity
資料行為 0 或更少時設定資料行錯誤。 資料列變更事件處理常式應該類似下列範例。
在資料列變更時驗證資料 (Visual Basic)
在 [DataSet 設計工具] 中開啟資料集。 如需詳細資訊,請參閱逐步解說:在 DataSet 設計工具中建立資料集。
按兩下您要驗證的資料表的標題列。 此動作會自動在資料集的部分類別檔案中建立 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#)
在 [DataSet 設計工具] 中開啟資料集。 如需詳細資訊,請參閱逐步解說:在 DataSet 設計工具中建立資料集。
按兩下您要驗證的資料表的標題列。 此動作會建立 DataTable 的部分類別檔案。
注意
DataSet 設計工具不會自動建立 RowChanging 事件的事件處理常式。 您必須建立方法來處理 RowChanging 事件,並執行程式碼來連結資料表初始化方法中的事件。
將下列程式碼複製到部分類別:
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 列舉中的值來追蹤該資料列的目前狀態。 您可以呼叫 DataSet 或 DataTable 的 GetChanges
方法,從資料集或資料表傳回已變更的資料列。 您可以藉由呼叫資料集的 HasChanges 方法,在呼叫 GetChanges
之前驗證變更存在。
注意
將變更認可至資料集或資料表之後 (藉由呼叫 AcceptChanges 方法),GetChanges
方法不會傳回任何資料。 如果您的應用程式需要處理變更的資料列,您必須先處理變更,才能呼叫 AcceptChanges
方法。
呼叫資料集或資料表的 GetChanges 方法會傳回只包含已變更的記錄的新資料集或資料表。 如果您想要取得特定記錄,例如,僅新記錄或僅修改過的記錄,您可以將 DataRowState 列舉中的值以參數形式傳遞至 GetChanges
方法。
使用 DataRowVersion 列舉來存取不同版本的資料列 (例如,處理資料列之前資料列的原始值)。
從資料集取得所有已變更的記錄
呼叫資料集的 GetChanges 方法。
下列範例會建立名為
changedRecords
的新資料集,並從名為dataSet1
的另一個資料集將所有已變更的記錄填入它。
從資料表取得所有已變更的記錄
呼叫 DataTable 的 GetChanges 方法。
下列範例會建立名為
changedRecordsTable
的新資料表,並從名為dataTable1
的另一個資料表將所有已變更的記錄填入它。
取得具有特定資料列狀態的所有記錄
呼叫資料集或資料表的
GetChanges
方法,並將 DataRowState 列舉值以引數形式傳遞。下列範例示範如何建立名為
addedRecords
的新資料集,並只使用已新增至dataSet1
資料集的記錄填入它。下列範例示範如何傳回最近新增至
Customers
資料表的所有記錄:
存取 DataRow 的原始版本
對資料列進行變更時,資料集會保留資料列的原始 (Original) 和新版本 (Current)。 例如,在呼叫 AcceptChanges
方法之前,您的應用程式可以存取不同版本的記錄 (如 DataRowVersion 列舉中所定義),並據以處理變更。
注意
只有在已編輯資料列之後,以及呼叫 AcceptChanges
方法之前,才會存在不同的資料列版本。 呼叫 AcceptChanges
方法之後,目前和原始版本都相同。
傳遞 DataRowVersion 值以及資料行索引 (或資料行名稱做為字串),會從該資料行的特定資料列版本傳回值。 在 ColumnChanging 和 ColumnChanged 事件期間,會識別變更的資料行。 這是針對驗證目的檢查不同資料列版本的好時機。 不過,如果您暫時暫止條件約束,則不會引發這些事件,而且您將必須以程式設計方式識別哪些資料行已變更。 您可以逐一查看 Columns 集合並比較不同的 DataRowVersion 值來執行此動作。
取得記錄的原始版本
傳入您要傳回的資料列的 DataRowVersion,以存取資料行的值。
下列範例示範如何使用 DataRowVersion 值來取得 DataRow 中
CompanyName
欄位的原始值:
存取 DataRow 的目前版本
取得記錄的目前版本
存取資料行的值,然後將參數新增至索引,指出您要傳回的資料列版本。
下列範例示範如何使用 DataRowVersion 值來取得 DataRow 中
CompanyName
欄位的目前值: