none
TabelAdapter做Update有時成功有時失敗,求解惑 RRS feed

  • 問題

  • 各位先進們好

    我寫好一支公司系統表單,在做測試時發生一些問題

    我在Form上建立一個DataGridView元件,指定資料來源後IDE自動產生了TabelAdapter與BindingSource

    TabelAdapter以下簡稱「TA」  BindingSource以下簡稱「BS」

    程式開始做BeginTranscation  鎖定型態 IsolationLevel.Serializable

    我在DataGrid上新增了一筆產品資料,在RowValidating事件作驗證,RowValidated事件做TA.Update(資料表)

    輸入產品編號、品名、數量、售價、金額、交貨日,資料插入成功

    測試在此資料直接重新輸入內容(不刪除  直接覆蓋) = 另一個產品資料、品名、數量、售價、金額、交貨日,Update有時成功有時失敗

    查看資料表BS.Position位置,在即時運算視窗用DataRowVersion看資料列Current資料 Original資料

    確認Original=原資料   Current=本次輸入資料

    TA在資料集中的UpdateCommand是全欄位Update 欄位名稱=@欄位名稱  where條件是@Original欄位名稱

    錯誤訊息:

    這訊息應該是SQL資料庫找不到原資料可以做更新

    可是我用with (NOLOCK)指令查看SQL資料庫中的資料表,是有原資料存在的

    請教各位先進,在不寫明確的SQL Update指令下,我應該怎麼做才能正確的Update資料...



    • 已編輯 GISK 2015年12月16日 上午 01:20
    2015年12月16日 上午 01:17

解答

  • 主管申請技術支援,問題解決
    支援工程師表示TA的UpdateCommand裡不應把PK鍵當成SET目標,Where條件只保留PK鍵就好
    不過我認為應該是後面的Where條件有被改到,造成找不到原資料可以更新而傳回錯誤


    資料表的資料已變更,但DataRowVersion.Current和DataRowVersion.Original相同
    支援工程師說這是因為BS處於資料變更狀態,資料未確認就不會將值寫入DataRowVersion.Current
    呼叫BS.EndEdit() 將暫止的變更套用至基礎資料來源,讓DataRowVersion.Current更改,TA.Update就能將資料寫回了

    參考網址:https://msdn.microsoft.com/zh-tw/library/system.windows.forms.bindingsource.endedit(v=vs.110).aspx



    • 已編輯 GISK 2015年12月22日 上午 09:18
    • 已標示為解答 GISK 2015年12月22日 上午 09:19
    2015年12月22日 上午 09:17

所有回覆

  • 並行違規是同一筆記錄被多次修改造成的, 您在完成更新記錄後是否有呼叫DataSet的AcceptChanges方法?
    2015年12月16日 上午 04:08
  • tihs 您好

    A資料輸入後執行TA.Update後都沒有呼叫AcceptChanges

    A資料輸入後,TA.Update之前,查看資料表DataRowVersion.Original是空值 .Current是輸入資料

    執行TA.Update,進入SQL資料庫使用with (nolock)查看資料表,資料插入成功,BS指標指向DataGrid新的空白列

    將BS指標指回第1筆,輸入B資料覆蓋原資料 (希望直接Update掉第1筆,而不是刪除再新增)

    輸入完畢,RowValidated事件執行TA.Update 出現並行違規

    但有些資料可以正常Update,有些會出現並行違規



    把可以正常覆蓋的資料當C資料 (即C資料覆蓋A後Update是成功的,B資料覆蓋A的Update是違規的)

    資料庫RollBack,資料表清空,插入會出現違規的B資料

    插入成功,BS指標指向DataGrid新的空白列

    BS指標移回,將C資料覆蓋B資料,Update出現並行違規

    重複上列步驟,將A資料覆蓋B資料,Update出現並行違規

    結果:A與C可以互相覆蓋,Update會正常寫回資料庫、B資料無法覆蓋,也無法被覆蓋


    ====================新問題====================

    我在DataGrid上帶出一張採購單的資料(已預先填上廠商交貨日期),使用者只需輸入採購數量

    採購數量輸入完畢後程式在背景處理庫存取用,發現可以取庫時會變更這張採購單的廠商交貨日

    BS.Current!交貨日期=庫存取用日期

    可是TA.Update完後發現SQL資料庫 資料表的日期欄位沒有變成庫存取用日期

    查看 BS.Position的DataRowVersion.Current=原日期    DataRowVersion.Original=原日期

    但是 資料集-資料表的資料已經改成 庫存取用日期 了

    為什麼DataRowVersion.Current會是原日期呢?

    P.S. 程式內沒有呼叫 AcceptChangs方法



    • 已編輯 GISK 2015年12月16日 上午 07:39
    2015年12月16日 上午 05:59
  • TA.Update後必須呼叫AcceptChanges
    2015年12月16日 下午 12:29
  • tihs 您好

    TA.Update之後做AcceptChanges還是同樣情形

    可以互相覆蓋的A、C資料,沒有AcceptChangs也可以寫回,重複多次都沒問題

    但是B資料就無法...

    2015年12月17日 上午 04:05
  • 主管申請技術支援,問題解決
    支援工程師表示TA的UpdateCommand裡不應把PK鍵當成SET目標,Where條件只保留PK鍵就好
    不過我認為應該是後面的Where條件有被改到,造成找不到原資料可以更新而傳回錯誤


    資料表的資料已變更,但DataRowVersion.Current和DataRowVersion.Original相同
    支援工程師說這是因為BS處於資料變更狀態,資料未確認就不會將值寫入DataRowVersion.Current
    呼叫BS.EndEdit() 將暫止的變更套用至基礎資料來源,讓DataRowVersion.Current更改,TA.Update就能將資料寫回了

    參考網址:https://msdn.microsoft.com/zh-tw/library/system.windows.forms.bindingsource.endedit(v=vs.110).aspx



    • 已編輯 GISK 2015年12月22日 上午 09:18
    • 已標示為解答 GISK 2015年12月22日 上午 09:19
    2015年12月22日 上午 09:17