我有一个场景,它需要在表中添加记录,然后 - 如果添加了记录,则在云上创建资源,然后如果在云上创建资源,则使用资源标识符更新表中的记录。所以,它们是3个操作,我想在它们中的任何一个都没有成功时恢复所有这些操作。
我们一次性使用TransactionScope进行多个Db操作,但我想知道如何实现这一目标?感谢您的帮助!
修改
PS:可能有许多类似的操作 - 比如序列中的10个或更多,它们甚至可能与数据库操作无关。他们可能只是按顺序创建10个文件 - 所以当任何文件创建失败时 - 所有以前的文件都应该删除/撤消。
答案 0 :(得分:2)
如何使用命令模式方式?它可能不是完美的命令模式实现,但非常接近。见下文:
[webclient]
10.20.30.40
[appserver]
10.20.30.41
同样,您将创建用于在db中创建云资源和更新记录的命令。在主代码中,您可以保存ICommand对象的集合并执行每个对象。
public interface ICommand {
ICommandResult Execute();
ICommandResult Rollback();
}
public interface ICommandResult {
bool Success { get; set; }
object Data { get; set; }
Exception Error { get; set; }
}
public class CommandResult : ICommandResult {
public bool Success { get; set; }
public object Data { get; set; }
public Exception Error { get; set; }
}
public class AddToDBCommand : ICommand {
private ICommandResult result;
private int newRecordId;
public AddToDBCommand(<params_if_any>) {
result = new CommandResult();
}
public ICommandResult Execute() {
try {
// insert record into db
result.Success = true;
result.Data = 10; // new record id
}
catch (Exception ex) {
result.Success = false;
result.Error = ex;
}
return result;
}
public ICommandResult Rollback() {
try {
// delete record inserted by this command instance
// use ICommandResult.Data to get the 'record id' for deletion
Console.WriteLine("Rolling back insertion of record id: " + result.Data);
// set Success
}
catch(Exception ex) {
// set Success and Error
// I'm not sure what you want to do in such case
}
return result;
}
}
然后在循环中,您可以调用var commands = new List<ICommand>
{
new AddToDBCommand(<params_if_any>),
new AddToCloudCommand(<params_if_any>),
new UpdateInDBCommand(<param_if_any>)
};
,如果它返回Execute
,则在集合中记录当前命令索引并向后循环,同时在每个命令上调用Success = false
。
答案 1 :(得分:0)
我假设您使用Azure作为云。
所以要支持你需要的交易 -
1. Azure上的弹性数据库,支持事务。
2.您需要使用.NET Framework 4.6.1或更高版本才能使用分布式事务。
我鼓励您浏览https://docs.microsoft.com/en-us/azure/sql-database/sql-database-elastic-transactions-overview
现在考虑到交易范围,在你的情况下让我们分三步。
事务范围完成后,您需要检查第3步中添加的记录是否存在。如果没有,则需要通过删除来手动回滚资源创建。