如何在单个事务中执行多个操作

时间:2017-05-05 05:15:11

标签: c# design-patterns architecture

我有一个场景,它需要在表中添加记录,然后 - 如果添加了记录,则在云上创建资源,然后如果在云上创建资源,则使用资源标识符更新表中的记录。所以,它们是3个操作,我想在它们中的任何一个都没有成功时恢复所有这些操作。

我们一次性使用TransactionScope进行多个Db操作,但我想知道如何实现这一目标?感谢您的帮助!

修改

PS:可能有许多类似的操作 - 比如序列中的10个或更多,它们甚至可能与数据库操作无关。他们可能只是按顺序创建10个文件 - 所以当任何文件创建失败时 - 所有以前的文件都应该删除/撤消。

2 个答案:

答案 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

现在考虑到交易范围,在你的情况下让我们分三步。

  1. 将记录添加到表格 -
    如果失败了,那我就不用担心了。
  2. 在云中创建资源 -
    如果此操作失败,则将回滚添加的记录。
  3. 更新表中创建资源ID的记录。
    如果失败,则回滚1步。
  4. 事务范围完成后,您需要检查第3步中添加的记录是否存在。如果没有,则需要通过删除来手动回滚资源创建。