(一) 序幕
當DataSet中同時包含主/子表(主鍵表/外鍵表)時,有時候關係限制太嚴格:
例如, 關係資料庫完整性規則:
1.實體完整性. 主鍵表中主鍵不準為空.
2.參考完整性. 外鍵表中外鍵的值必須與主鍵表中的主鍵對應.
要麼為空,要麼為主鍵表中的一主鍵值.
3.自訂完整性.
如果DataSet表中定義的多表關係限制太嚴密,直接用Update方法
DataSet中多重表格一起提交時,有可能不滿足完整性規則,會發生錯誤,
原因: 舉例,設為兩個表: CompanyMain(公司主表)和CompanySon(公司子表)
CompanyMain(公司主表)主要儲存一個公司的基本資料,CompanySon(公司子表)
主要儲存此公司的一些客戶的資訊. 並且公司主表中的(ID)與子表中的(BelongID)
建立關聯,即主外鍵關係; 一個公司對應多個客戶,即ID:BelongID = 1 : n關係.
主表的ID為自動產生編號.
那麼:
在新增公司介面,一起提交時,系統是不會遵守"資料庫完整性規則"來更新到資料庫的.
如果它先更新子表,再更新主表有可能就會報錯. 原因是主表的公司資訊還沒有插入
到資料庫中的表,也就沒有產生公司編號: ID,則子表更新時就會沒有對應的BelongID.
這時如果設定了: "外鍵表中的外鍵不為null"完整性規則,就會引發異常.
這只是一種出錯的可能,還有更多的出錯可能性,在分佈式設計中更容易出現這樣的錯誤.
(二). 解決辦法
一般遵守以下幾條規則,就會避免大量的出錯機率.
1規則. 在DataSet更新之前按<表> 和<表的RowState屬性>進行拆分提交
I. 按<表> 進行拆分提交意思是說:
對DataSet 中的表不是一起提交,而是一次提交一個表,進行多次提交
II.按<表的RowState屬性>進行拆分提交意思是說:
對DataSet中的單一表根據RowState屬性,再進行拆分,對RowState
相同的進行一次提交,也是提交多次
2.規則.
在規則1基礎上, 先更新狀態為<新增> 和<修改> 的,再更新<刪除的>
即: 先更新DataRowState 值為: Added和Modified的,再更新: Deleted的.
3 .規則
在規則1和規則2基礎上,如果DataRowState為Added和Modified,則先更新主表,後更新子表.在規則1和規則2基礎上,如果
DataRowState為Deleted,則先更新子表,後更新主表.
(三) 歸納上面三條規則,如下:
1.將DataSet中的表拆分,並根據RowState將各個表記錄進行分組並存儲在不同的數據集中
//這裡要存儲在DataSet中,是因為: Update接受的是DataSet的參數,還有WebService只支援
//DataSet,對其進行序列化操作
代碼範例:
設待更新的資料集為: dsCompany(裡麵包括兩個表,分別為主表和子表,並儲存了
資料,待更新)
//dtCompanyMain儲存公司主表資訊,dtCompanySon儲存公司子表資訊
DataTable dtCompanyMail = ds.Tables["dtCompanyMain"].Clone(); //分離出主表資料
並儲存另一物件
DataTable dtCompanySon = ds.Talbes[ "dtCompanySon"].Clone(); //分離出子表資料
並儲存另一個物件
DataSet dsAdded = new DataSet(); //存放主表新增的資料
DataSet dsMidified = new DataSet(); //儲存主表格編輯的行記錄
DataSet dsDeleted = new DataSet(); //儲存主表刪除的行記錄
dsAdded = dtCompanyMain.GetChanges(DataRowState.Added); //取得主表中新增的行
記錄集
dsMidified = dtCompanyMain.GetChanges (DataRowState.Modified); //取得主表中
編輯
的行記錄集dsDeleted = dtCompanyMain.GetChanges(DataRowState.Deleted); //取得主表中刪除的
行記錄集
2.更新主表DataRowState狀態為: Added和Modified的記錄.
SqlDataAdapter.Update(dsAdded,"dtCompanyMain"); //更新新增的記錄集到資料庫
SqlDataAdapter.Update(dsModified,"dtCompanyMain"); //更新修改的記錄集到資料庫3.更新子集到
資料庫
3.更新子表DataRowState狀態為: Added和Modified的記錄
............. //代碼省略,跟2主表更新類似
4.更新子表DataRowState狀態為: Deleted的記錄.
... ......... // 程式碼省略,與下面5類似
5.更新主表DataRowState狀態為: Deleted的記錄
SqlDataAdapter.Update(dsDeleted,"dtCompanyMain"); //更新修改的記錄集到資料庫
謝謝閱讀!