簡體   English   中英

NHibernate IStatelessSession CreateQuery失敗

[英]NHibernate IStatelessSession CreateQuery failure

當我們上周五發布時,我收到了一個錯誤,我沒有被接受。 錯誤消息是:

could not execute update query[SQL: delete from dbo.MyTable where col1=? and col2=? and col3=? and col4=? and col5=?]

我的C#代碼如下:

var hqlDelete = "DELETE MyTable m WHERE m.Col1 = :var_1 AND m.Col2 = :var_2 AND m.Col3= :var_3 AND m.Col4 = :var_4 AND m.Col5= :var_5";
var deletedEntities = session.CreateQuery(hqlDelete)
                             .SetString("var_1", variable1)
                             .SetString("var_2", variable2)
                             .SetString("var_3", variable3)
                             .SetString("var_4", variable4)
                             .SetString("var_5", variable5)
                             .ExecuteUpdate();
transaction.Commit();
session.Close();

現在,正如我所說,在接受測試時不會觸發錯誤。 另外,當我使用生產數據庫(開發人員所在地的代碼)進行測試時,它也可以正常工作。

當我調用Web服務並向其發布“度量”時,將觸發代碼。 唯一的區別是,我在測試時調用該服務,而在生產時,另一家公司將度量值發送到Web服務。

我認為這可能與會話/事務的數量有關,但這並不能真正解釋為什么變量顯示為? 在錯誤消息中。

有任何想法嗎? 我是否可以提供更多信息,以便您可以幫助我?

編輯:InnerExeption是

{"Transaction (Process ID 68) was deadlocked on lock | communication buffer resources with another process and has been chosen as the deadlock victim. Rerun the transaction."}

解決死鎖可能很困難,尤其是在使用ORM時。 死鎖通常是由於不同的進程(或線程)沒有以相同的順序獲取數據庫對象上的鎖而導致彼此等待而發生的。

ORM不會給您太多控制鎖的順序。 您可以重新整理查詢順序,但這可能很乏味。 特別是在緩存導致其中一些無法訪問數據庫時。 而且,應該在使用同一數據庫的任何其他應用程序上以相同的順序進行操作。

您可能會檢測到死鎖錯誤,然后執行以下消息:重試整個過程。 使用NHibernate,這意味着放棄當前會話,然后重試整個工作單元。

如果您的數據庫是SQL Server,則有一個默認設置會大大增加死鎖的風險:禁用讀取提交的快照模式 如果在數據庫上將其禁用,則可以通過啟用它來大大降低死鎖風險。 此模式允許處於讀取提交隔離級別的讀取停止發出讀取鎖定。

您可以通過以下方式檢查此設置

select snapshot_isolation_state_desc, is_read_committed_snapshot_on
    from sys.databases 
    where name = 'YourDbName'

您可以通過以下方式啟用此設置

alter database YourDbName
    set allow_snapshot_isolation on

alter database YourDbName
    set read_committed_snapshot on

這要求目標數據庫上沒有正在運行的事務。 當然,這需要具有數據庫管理員權限。

在我沒有選擇更改此設置的應用程序上,我不得不采用一種更古怪的方式:將NHibernate默認隔離模式( connection.isolation配置參數 )設置為ReadUncommitted 我的應用程序大多數情況下是只讀的,我正在顯式地提升必須讀取然后寫入數據的少數事務的隔離模式session.BeginTransaction(System.Data.IsolationLevel.ReadCommitted)例如,使用session.BeginTransaction(System.Data.IsolationLevel.ReadCommitted) )。

您還應該檢查所有使用數據庫的應用程序當前使用的隔離模式:其中某些使用的隔離級別是否比實際需要的隔離級別高? (如果可能,應避免使用RepeatableReadSerializable 。)這是一個耗時的過程,因為在研究每個用例以確定合適的最小隔離級別時,它需要對隔離級別有很好的了解。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM