[英]can you have multiple transactions occur inside one session in nhibernate? And is it a bad idea?
我正在考慮為NHibernate持久層創建自己的IUnitOfWork
實現。
似乎正確的方法是在構造函數中實例化ISession
和ITransaction
,然后在析構函數或Dispose()
方法中進行Dispose()
。
當然,如果有人調用Save()
方法,那么ISession
將被刷新並且ITransaction
將完成,因此在調用Save()
,將再次沒有有效的打開事務來Save()
...除非我提交了第一筆交易並立即開通了另一筆新交易。 但這是個好主意嗎?
在設計方面,做一個提交操作是有意義的,但我不一定能控制代碼,而其他開發人員可能不太遵守UnitOfWork模式。
通過嘗試使UnitOfWork容忍每個會話的多個事務,我會失去/獲得任何東西嗎? 我應該檢查一個打開的事務,如果它已經被提交則拋出異常,而不是進行新的事務嗎?
回答第一個問題:是的,可以在一個會話中擁有多個事務。
是個好主意嗎? 這取決於。
問題是第一個事務中的數據更改將被提交,而不確定整個工作單元(會話)是否在最后提交。 當你得到一個稍后的事務中的StaleObjectException時,你已經提交了一些數據。 請注意,這種異常使您的會話無法使用,無論如何您必須銷毀它。 然后很難重新開始並再試一次。
我想說,在這種情況下它運作良好:
UI應用程序
錯誤由用戶以交互方式處理。 這意味着用戶可以在錯誤的情況下查看實際存儲的內容並重復他所做的更改。
更改僅在最后一個事務中刷新
由NH實施的會話僅在最后或“必要時”刷新更改。 因此,在會話提交之前,可以保留內存中的更改。 問題是NH需要在每次查詢之前刷新會話,這很難控制。 它可以關閉,這會導致副作用。 在編寫簡單的事務時,您可以控制它。 在復雜的系統中,幾乎不可能確保沒有任何問題。
簡單方法(tm)
我編寫了一個非常大的客戶端 - 服務器系統的持久層。 在這樣的系統中,您沒有用戶直接處理錯誤。 您需要處理系統中的錯誤並以一致的狀態將控制權返回給客戶端。
我將整個事務處理簡化為絕對最小化,以使其穩定並且“白痴證明”。 我總是創建一個會話和一個事務,它會被提交或不提交。
有多個選項可用於實現具有工作單元的nhibernate嵌套事務。
在這里,我使用Command模式作為工作單元。
public interface IAction
{
void Execute();
}
public abstract class Action<T> : IAction, IDisposable where T : Action<T>
{
public void Execute()
{
try
{
//Start unit of work by your unit of work pattern or
transaction.Begin();
OnExecute();
//End Unit of work
transaction.Commit();
}
catch (Exception e)
{
transaction.Rollback();
throw e;
}
}
protected abstract void OnExecute();
public void Dispose()
{
}
}
public class MyBusinessLogic : Action<MyBusinessLogic>
{
protected override void OnExecute()
{
//Implementation
}
}
public class MyAnotherBusinessLogic : Action<MyAnotherBusinessLogic>
{
protected override void OnExecute()
{
//Nested transaction
MyBusinessLogic logic = new MyBusinessLogic();
logic.Execute();
}
}
我認為每單位工作一次交易的解決方案限制性太強。 在某些環境中,人們可能需要能夠在每個會話中執行多個事務。 我自己明確地管理交易,它似乎是一個靈活的解決方案。
public interface IUnitOfWork: IDisposable
{
IGenericTransaction BeginTransaction();
}
public interface IGenericTransaction: IDisposable
{
void Commit();
void Rollback();
}
public class NhUnitOfWork: IUnitOfWork
{
private readonly ISession _session;
public ISession Session
{
get { return _session; }
}
public NhUnitOfWork(ISession session)
{
_session = session;
}
public IGenericTransaction BeginTransaction()
{
return new NhTransaction(_session.BeginTransaction());
}
public void Dispose()
{
_session.Dispose();
}
}
public class NhTransaction: IGenericTransaction
{
private readonly ITransaction _transaction;
public NhTransaction(ITransaction transaction)
{
_transaction = transaction;
}
public void Commit()
{
_transaction.Commit();
}
public void Rollback()
{
_transaction.Rollback();
}
public void Dispose()
{
_transaction.Dispose();
}
}
用法如下所示。 它很容易融入任何模式。
public void Do(IUnitOfWork uow)
{
using (var tx = uow.BeginTransaction()) {
// DAL calls
tx.Commit();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.