Dispose() 如何知道它是由于异常而被调用的?
我想编写一个简单的工作单元类,其行为如下:
using (var unitOfWork = new UnitOfWork())
{
// Call the data access module and don't worry about transactions.
// Let the Unit of Work open a session, begin a transaction and then commit it.
}
这就是我到目前为止所拥有的(如果您认为我的设计错误,欢迎任何评论):
class UnitOfWork : IDisposable
{
ISession _session;
ITransation _transaction;
.
.
.
void Dispose()
{
_transaction.Commit();
_session.Dispose();
}
}
我想做的是回滚事务以防数据访问代码抛出一些异常。所以 Dispose()
方法看起来像这样:
void Dispose()
{
if (Dispose was called because an exception was thrown)
{
_transaction.Commit();
}
else
{
_transaction.RollBack();
}
_session.Dispose();
}
这有意义吗?如果可以的话,该怎么办呢?
I'd like to write a simple unit of work class that would behave like this:
using (var unitOfWork = new UnitOfWork())
{
// Call the data access module and don't worry about transactions.
// Let the Unit of Work open a session, begin a transaction and then commit it.
}
This is what I have so far (any comments will be welcome if you think my design is wrong):
class UnitOfWork : IDisposable
{
ISession _session;
ITransation _transaction;
.
.
.
void Dispose()
{
_transaction.Commit();
_session.Dispose();
}
}
What I would like to do is to roll back the transaction in case the data acess code threw some exception. So the Dispose()
method would look something like:
void Dispose()
{
if (Dispose was called because an exception was thrown)
{
_transaction.Commit();
}
else
{
_transaction.RollBack();
}
_session.Dispose();
}
Does it make sense? And if so, how can it be done?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

发布评论
评论(5)
这里的游戏有点晚了,但请检查 Ayende 的这篇文章提供了一个(有点疯狂的)解决方案:
在 Dispose 方法中,您只需要弄清楚它是否“干净”地到达那里 - 即图如果在提交事务之前存在未处理的异常,则输出:
public class ExceptionDetector : IDisposable
{
public void Dispose()
{
if (Marshal.GetExceptionCode()==0)
Console.WriteLine("Completed Successfully!");
else
Console.WriteLine("Exception!");
}
}
Dispose
的要点是它始终运行。通过使用这种提交-回滚习惯用法,您不需要知道其中的区别。
using (var unitOfWork = new UnitOfWork())
{
// use unitOfWork here - No need to worry about transactions for this code.
unitOfWork.Commit();
}
在这里我们看到要么抛出异常,要么提交unitOfWork。然后我们可以在 UnitOfWork
中使用 bool 来跟踪 Commit 是否被执行。然后Dispose
可以Rollback不提交。这样,工作单元总是要么回滚,要么提交。
无论如何,我会避免将提交放在处置中。对于初学者来说,ITransaction.Commit
方法通常可能会抛出错误异常 - 这是完全正常的。但是,Dispose
方法不应该抛出异常。请参阅此链接并在 Stackoverflow 上搜索有关的更多深入信息为什么。
我正在大笔思考类似的事情
class UnitOfWork : IDisposable
{
ISession _session;
ITransation _transaction;
bool _commitTried;
// stuff goes here
void Commit()
{
_commitTried = true;
_transaction.Commit();
}
void Dispose()
{
if (!_commitTried) _transaction.Rollback();
_transaction.Dispose();
_session.Dispose();
}
}
我想说的是,完全忘记调用 Commit 的问题并不是那么大,因为除非提交,否则客户端代码将无法工作,因为事务是回滚
'ed并且不应用更改,这些更改将在夹具内或手动执行代码时发现。
我实际上尝试在一个项目中使用带有 lambda 的语法来处理这个问题,如下所示
_repository.InTransactionDo(ThisMethodIsRunInsideATransaction);
这样客户就不需要担心提交任何内容。实际上我最终对此感到后悔,因为它让事情变得太复杂了,并且希望我放弃上述方法。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
“Dispose()”应该与事务提交或回滚无关。您应该在 Dispose() 方法中处置您的事务。从长远来看,更改 Dispose() 方法的语义只会给您和使用您的类的其他人增加混乱。
Transaction 的 Commit() 和 RollBack() 方法与 Dispose() 方法没有任何关系,因为这两个方法和 Dispose() 之间没有相关性,因为无论最终结果是什么,您都必须处理事务。
对于连接和事务来说,这是正确使用的模式。请注意,Roolback(0 涉及异常(而不是 dispose)),
因此请使用 Commit()、Roolback() 和 Dispose() 方法在 UnitOfWork 中模仿此模式。
The "Dispose()" should have nothing to do with transaction commit or rollback. You should dispose you transaction in your Dispose() method. Changing the semantics of your Dispose() method will only add to confusion in the long run for you and anyone else using your class.
The Transaction's Commit() and RollBack() methods have nothing whatsoever to do with a Dispose() method since there is no correlation between these two method and Dispose(), since you have to dispose a transaction no matter what the final outcome is.
This is the correct pattern to use as regards connections and transactions. Notice that Roolback(0 relates to an exception (and not dispose)
So mimic this pattern in your UnitOfWork, with methods for Commit(), Roolback() and Dispose().