1
我有一個可以被多個程序訪問的SQL Server數據庫。這些程序用C#編寫,並使用Fluent NHibernate作爲ORM。但是數據庫中存在一些對象(稱爲令牌),根據域邏輯,不應允許多個進程/線程同時處理它們。正確處理StaleObjectStateException
我試圖通過NHIbernate版本鎖定實現此目的。我有以下映射
mapping.OptimisticLock.Version();
mapping.Version(token => token.VersionTimestamp).Generated.Always().UnsavedValue(null).Access.Property().CustomSqlType("timestamp").Nullable();
和下面的代碼:
var token = Session.Get<Token>(tokenId);
if (token.Status != TokenStatus.Available)
return new FailedResult("Token not available");
try
{
token.Status = TokenStatus.Locked;
Session.SaveOrUpdate(token);
}
catch (StaleObjectStateException)
{
WriteLogsToDb(); // <- another StaleObjectStateException thrown here
return new FailedResult("Could not acquire token");
}
ProcessToken(token); // do stuff that isn't allowed to be done concurrently by multiple threads/processes
token.Status = TokenStatus.Available;
Session.SaveOrUpdate(token);
return new SuccessResult();
的問題是,我得到一個StaleObjectStateException
後,我無法保存任何東西到DB(即使是沒有版本的實體映射)。我得到另一個StaleObjectStateException
。但是我無法鎖定令牌後,我真的需要在DB中寫入日誌和其他一些東西。
什麼是正確的方法來做到這一點? NHibernate的這種行爲的原因是什麼?
可悲的是,加入'Session.Evict'或'Session.Refresh'沒有效果。我忘記提到'Session.SaveOrUpdate'是一個覆蓋,它在內部創建一個事務,調用NHibernate的'SaveOrUpdate',然後提交事務。 – holdenmcgrohen
請給我看看您正在調用WriteLogsToDb()的異常文本。和這種方法的代碼。 –
在關於併發性的Ayende帖子中:http://ayende.com/blog/3946/nhibernate-mapping-concurrency 我發現這個: 如果更新因爲行更新而失敗,我們將得到一個StaleObjectException。與所有例外情況一樣,這會使會話不符合使用條件,您將不得不創建新會話來處理它._ 因此,您必須創建一個新會話才能在此情況下寫入日誌。 –