.NET 中的嵌套事务
我怎样才能执行与此等效的操作? 我的理解是,这对于 TransactionScopes 来说是不可能的,但我想在某些方面实现相同的效果其他方式:
业务逻辑类:
public bool Bar()
{
try
{
using (var tsWork = new TransactionScope())
{
ComplicatedDataImportCode(somedata);
FlagRecordInDatabaseAsImported(); // this is the same record that's modified in the catch
tsWork.Complete();
return true;
}
catch (DuplicateDataException err)
{
// if we got here, the above transaction should have rolled back,
// so take that same record in the database and update it to "Duplicate".
FlagSameRecordInDatabaseAsDuplicate(err.Message);
}
return false;
}
现在这工作正常,直到我将所有这些封装在事务中(可能是我想在执行断言后回滚的集成测试)。
简单的测试来证明我的观点:
public void CanTest()
{
// Arrange
var foo = new Foo();
using (var ts = new TransactionScope())
{
// Act
var success = foo.Bar();
// Assert
if (success)
{
Assert.That(SomethingThatTestsThatTheDataWasImported);
}
else
{
Assert.That(SomethingThatTestsThatTheRecordWasMarkedAsDuplicate);
}
// Now that we have been able to perform our Asserts, rollback.
}
}
最终,可以修改 Foo.Bar()
中的代码以适应解决方案,但是,ComplicatedDataImportCode()
中的代码不能修改为这个解决方案,因此是我真正需要确保在故障场景中正确回滚的解决方案。
再次,根据我在本问题开头引用的帖子,我明白 TransactionScopes 不能用于执行此操作。我在这里使用 TransactionScopes 来指示我想要做什么,并且正在寻找实现此功能的最佳替代方法。
How can I perform the equivalent of this? My understanding is that this is impossible with TransactionScopes but I'd like to accomplish the equivalent in some other way:
Business Logic class:
public bool Bar()
{
try
{
using (var tsWork = new TransactionScope())
{
ComplicatedDataImportCode(somedata);
FlagRecordInDatabaseAsImported(); // this is the same record that's modified in the catch
tsWork.Complete();
return true;
}
catch (DuplicateDataException err)
{
// if we got here, the above transaction should have rolled back,
// so take that same record in the database and update it to "Duplicate".
FlagSameRecordInDatabaseAsDuplicate(err.Message);
}
return false;
}
Now this works fine, until I encapsulate all of this inside of a transaction (perhaps an integration test that I want to rollback after performing asserts).
Simple test to prove my point:
public void CanTest()
{
// Arrange
var foo = new Foo();
using (var ts = new TransactionScope())
{
// Act
var success = foo.Bar();
// Assert
if (success)
{
Assert.That(SomethingThatTestsThatTheDataWasImported);
}
else
{
Assert.That(SomethingThatTestsThatTheRecordWasMarkedAsDuplicate);
}
// Now that we have been able to perform our Asserts, rollback.
}
}
Ultimately, the code in Foo.Bar()
can be modified to accommodate a solution however, the code in ComplicatedDataImportCode()
cannot be modified for this solution, and is consequently what I really need to make sure I properly rollback in the failure scenario.
Again, I understand that TransactionScopes cannot be used to do this, according to the post that I referenced at the beginning of this question. I used TransactionScopes here to indicate what I wanted to do, and am looking for the best alternative way to implement this functionality.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是不是您正在使用的 DBMS 必须支持这一点?
例如,SQL Server 并不真正支持嵌套事务,但是,对于 SQL Server,您可以使用 保存点。
一篇文章我几年前写的在我的博客上。
Isn't it so that this must be supported by the DBMS you're using ?
SQL Server doesn't really support nested transactions for instance, however, with SQL Server you can use savepoints.
An article I've written some years ago on my blog.
如果您可以获取
ComplicatedDataImportCode
正在使用的活动数据库连接,则只需运行BEGIN TRAN
和ROLLBACK TRAN
即可那个连接。If you can get a hold of the active DB connection that
ComplicatedDataImportCode
is using, you should just have to run aBEGIN TRAN
andROLLBACK TRAN
on that connection.