2011-08-17 58 views
1

所以我有一套複雜的代碼(由其他人編寫),它具有在最終執行Commit()更改前執行許多數據庫操作的功能。DbTransaction.Commit回滾,導致代碼中斷?

雖然這裏存在的問題是代碼中存在子函數,它們被調用,如getThis或getThat,它們具有execute()和queryDatabase()函數。代碼在某些情況下(並非所有情況下)都會導致錯誤,它會在此處「執行」或「queryDatabase」中凍結。從本質上講,我認爲這與在提交更改之前代碼需要來自這些queryDatabase命令的數據有關。

刪除數據訪問指針傳遞給這些子函數(因此它們不是提交的一部分)後,突然代碼成功通過。

什麼是正確的方式來使用Commit()或者我應該擺脫它而不使用這些交易功能?讓代碼立即做一切?

我什至不能找到最後的錯誤,只是另一個模糊的「連接參數null」SystemArgumentNullException,它以某種方式連接到它是一個事務。

System.ArgumentNullException: Value cannot be null 
Parameter name: connection 
at Data.Database.PrepareCommand(DbCommand command, DbConnection connection) 

很難張貼的代碼,因爲它跨越了至少20頁不同的文件(是的,原來的開發商不知道KISS)。

回答

2

的Transaction.Connection將被設置爲空交易後承諾,這可能是爲什麼,如果代碼是圍繞Transaction.Connection傳遞作爲參考的連接設置爲null的原因所有的子功能。交易不擁有連接,所以不應該傳遞給其他子功能。

這聽起來像連接正在傳遞所有的地方。更好的辦法是放在一個using塊的連接,並只將需要在THT using塊連接,並assoicated交易與它的命令。

這是一個基本的模式:

using(DbConnection connection = ...) 

{ 

    connection.Open(); 

    using(DbTransaction transaction = connection.BeginTransaction(...)) 

    { 

     ... do stuff ... 

     transaction.Commit();   

    } // transaction rolled back here if an Exception is thrown before the call to Commit() 

} // connection closed here 

交易是必要的,如果代碼被保存到多個表/記錄。工作單位需要整體承擔而不是部分承擔。擺脫交易的一種方法是讓數據庫通過存儲過程直接管理它們。 BEGIN TRAN是在存儲過程中明確完成的,此時C#代碼不再管理它。

而且看一看的System.Transactions命名空間。我認爲使用它比管理連接本身上的事務更容易。

+0

我已經做到這一點:如果(_transaction!= NULL){ _transaction.Commit(); } _transaction = NULL; ----我的感覺是交易在這個系統中只是越野車。因爲它在每個queryDatabase或execute()中都會給出錯誤。它不適用於交易。或者,也許某種類型的數據庫類被傳遞給子函數的錯誤,它根本無法工作。 – Dexter

+0

我同意,這聽起來更像是一個系統/設計問題。對於數據庫中的查詢,如果需要,可以在沒有事務的情況下在單獨的連接上打開它們。這聽起來像在那裏混亂。 –

+0

你不會相信有多混亂。但是如果ASP.nET沒有發出這個星球上最糟糕的錯誤,我會更高興:「DataAccessException:System.Data.DataSet queryDatabase(System.String,net.cadat.dataManager.dbConn.StoredProcedureParameter [])System。 NullReferenceException:對象引用未設置爲對象的實例「-----誰知道錯誤在哪裏。它將錯誤指向db類文件(無法知道來自哪裏)。所有的DataAccess都作爲它們的副本傳遞給子函數(不通過引用傳遞),因此以某種方式將其複製到其他函數會導致錯誤。 – Dexter

1

DbTransaction.Commit()/ Rollback()事務對象進入「zombie」狀態後。 如果您打算繼續使用某些命令事務範圍通過設置事務屬性,他們必須從交易中分離的外空

+0

我不知道我的理解,正如我所說,有一個的BeginTransaction(),然後一些queryDatabase()執行(),然後提交()。它在每個queryDatabase上失敗並執行,在它提交之前。如果我在其他函數中創建一個新的數據訪問指針,那麼它們傳遞的很好。換句話說,事務在ASP.NET中是超級錯誤的(或者有些事情是無法解釋的,比如你可能無法調用事務中的任何查詢 - 那麼交易的最終目的是什麼?)。 – Dexter

0

什麼是使用commit()或我應該只是擺脫有道它並沒有使用這些交易功能?讓代碼立即做一切?

不要擺脫交易。它們有意義的設計是爲了保持數據的一致性。

+0

但它導致我錯誤遍及整個代碼,我無法修復它們。該代碼給出了荒謬的錯誤,我認爲這是ASP.nET系統性的問題,不給出描述性錯誤,調試不起作用,並試圖找到與日誌錯誤是永遠。我無法跟蹤了。它壞了。 ASP.NET不能正確地處理事務,如果是這樣,就不會有無意義的隨機錯誤(只有在傳入dataAccess時纔會發生;如果創建了新的dataAccess,則不會發生錯誤,因爲事務是錯誤的)。 – Dexter

1

事務通常應用於邏輯上代表單個工作單元的一組操作。換句話說,如果在一個事務中執行了三個操作,並且其中一個操作失敗或者調用了回滾,則結果應該反映實際發生在數據庫中的三個操作的結果。

因此,在您決定刪除交易之前,您需要確定原始開發人員的意圖和代碼(這可能並不容易!)。如果行動需要一起成功或失敗,則需要繼續使用該交易。如果每個操作都可以成功或失敗,則可能完全擺脫該事務,因爲大多數數據庫都具有單個調用的隱式事務。

幾條經驗法則:1.交易費用昂貴 - 儘可能晚地啓動並儘早提交; 2.通常(並非總是)不需要讀取/查詢落入包含寫入的事務內部。

Database Transactions

+0

我知道交易很有幫助。然而,在這種情況下,它們導致不可能修復錯誤,並含有'空連接'的模糊描述。此外,顯然交易本身導致問題,因爲數據庫調用發生錯誤(即使數據庫和連接工作正常)。很難確定在這裏進行交易是否重要,如果出現錯誤,我確實不介意任何空洞的「鬼影數據」,但這不是一個好習慣。 – Dexter

+0

底線是交易是需要的或者他們不是針對有問題的操作。您的團隊將需要破譯代碼並使交易使用正確,或者移除交易並承擔與此相關的風險。 –