c# - 实现 IEnlistmentNotification 时我应该在哪里执行操作?

标签 c# .net transactions transactionscope

我正在尝试通过实现 IEnlistmentNotification 来创建自定义“资源管理器”界面。该接口(interface)有以下方法:

  • 准备()
  • 提交()
  • 回滚()
  • 怀疑()

虽然很明显回滚代码应该放在 Rollback() 方法中,但我不确定我应该在哪个方法中实现执行实际操作的代码?它应该放在 Prepare() 或 Commit() 中,还是应该从 TransactionScope block 内部的外部代码调用的类中的其他自定义方法?

最佳答案

实际工作应该以另一种方法进行。 Prepare 和 Commit 用于实现两阶段提交机制。

模式如下:

using(var transaction = new TransactionScope())
{
    var rc1 = new ResourceManager();
    rc1.DoWork();
    var rc2 = new ResourceManager();
    rc2.DoWork();
    transaction.Complete();
}

在此示例中,DoWork 应执行操作。 当退出事务范围时,将调用两个资源管理器的 Prepare 方法。 如果他们都调用了 enlistment.Prepared();,那么将调用两个管理器的 Commit 方法。 该提交永远不会失败!

例如,在处理文件时, DoWork 应该重命名该文件以表明您正在处理它,然后读取并处理该文件。如果任何一个操作失败,它应该抛出异常导致调用回滚。 Rollback 应该将文件重命名回其原始名称。 Prepare 可以重命名文件以指示应该删除它并检查是否允许删除该文件。如果任一操作失败,它应该抛出异常。 Commit 然后会实际删除该文件。这不会失败,因为我们已经检查了安全性,但即使它失败了,也不应该抛出异常。

您实际上可以在 Prepare 方法中删除文件并调用 enlistment.Done();。这将表明不再需要对 Commit 的调用。但这样做的问题是,在您删除文件后,其他资源管理器可能会在其 Prepare 中抛出异常。因为您表示您已完成,所以不会调用您的回滚方法。即使调用了,您也无法恢复操作...

我希望这能解释一些事情......

关于c# - 实现 IEnlistmentNotification 时我应该在哪里执行操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21094406/

相关文章:

c# - 磁盘读/写时间的性能计数器

.net - TPL DataFlow 与 BlockingCollection

.net - SQLite 在使用密码在 Linux 上运行时抛出 "EntryPointNotFoundException: sqlite3_key"异常

与 NestJS 和 TypeORM 的交易——装饰器和单元测试

c# - 在Azure表存储中,如何原子地执行 "get or insert"?

C# Datagridview Checkbox Checked 事件 - 多行?

c# - 如何获取复选框列表控件中的选中项

c# - ProcessStartInfo.EnvironmentVariables 和 ProcessStartInfo.Environment 之间有什么区别

c# - 带有数据库和 ADO.NET Entity Framework 的 .NET TDD - 集成测试

tsql - 通过在脚本末尾使用 ROLLBACK 来测试 SQL 脚本是个好主意吗?