當DataSet中包含主/子表時,Update更新步驟:
(http://blog.csdn.net/chengking/archive/2005/10/03/494717.aspx)
(一) 說明
當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"); //更新修改的記錄集到資料庫