(一) 序幕
當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.更新子表DataRowState狀態為: Added和ModifIEd的記錄
............. //代碼省略,跟2主表更新類似
4.更新子表DataRowState狀態為: Deleted的記錄.
............ // 代碼省略,與下面5類似
5.更新主表DataRowState狀態為: Deleted的記錄
SqlDataAdapter.Update(dsDeleted,"dtCompanyMain"); //更新修改的記錄集到數據庫
謝謝閱讀!