实现带Out参数的委托调用:数据库事务装饰器模式遇技术难题
处理带Out参数的委托的事务安全执行方法
我完全懂你碰到的这个坎儿——标准的Action和Func用来封装事务错误处理简直顺手,但带out参数的方法就没法直接套现成的委托了。你自定义的FuncWithOut<T1, T2, TResult>路子是对的,接下来咱们就基于这个委托实现对应的安全执行逻辑,完美适配事务的提交/回滚需求。
第一步:实现适配FuncWithOut的安全执行方法
我们可以直接照搬你之前SafetyExecuteMethod(Action action)的思路,只是调整参数和返回值来适配带out参数的委托:
// 先确认你已经定义了这个自定义委托 public delegate TResult FuncWithOut<T1, T2, TResult>(T1 arg1, out T2 arg2); // 对应的事务安全执行方法 private TResult SafetyExecuteMethod<T1, T2, TResult>(FuncWithOut<T1, T2, TResult> func, T1 arg1, out T2 arg2) { TResult result = default; arg2 = default; // 必须先初始化out参数,否则编译器会报错 // 这里替换成你实际的数据库事务初始化逻辑,比如SqlConnection的BeginTransaction using (var transaction = YourDbConnection.BeginTransaction()) { try { // 执行传入的带out参数的业务方法 result = func(arg1, out arg2); // 执行成功则提交事务 transaction.Commit(); } catch (Exception ex) { // 出错立即回滚事务 transaction.Rollback(); // 这里可以添加你的错误处理逻辑,比如日志记录、异常包装等 Console.WriteLine($"事务执行失败:{ex.Message}"); throw; // 根据业务需求决定是否抛出异常 } } return result; }
第二步:实际调用示例
假设你有一个带out参数的数据库业务方法,比如创建用户并返回生成的用户ID:
// 模拟的业务方法:创建用户,out参数返回生成的用户ID,返回值是受影响行数 private int CreateUser(string username, out Guid userId) { // 这里写实际的数据库插入逻辑 userId = Guid.NewGuid(); Console.WriteLine($"创建用户:{username},ID:{userId}"); return 1; }
调用安全执行方法的方式和普通方法一致:
Guid newUserId; int affectedRows = SafetyExecuteMethod(CreateUser, "MaximChervyakov", out newUserId); Console.WriteLine($"执行结果:受影响行数{affectedRows},用户ID{newUserId}");
扩展:支持多个Out参数
如果你的业务方法需要多个out参数,只需要扩展自定义委托和对应的执行方法即可:
// 支持两个out参数的委托 public delegate TResult FuncWithOut<T1, T2, T3, TResult>(T1 arg1, out T2 arg2, out T3 arg3); // 对应的安全执行方法 private TResult SafetyExecuteMethod<T1, T2, T3, TResult>(FuncWithOut<T1, T2, T3, TResult> func, T1 arg1, out T2 arg2, out T3 arg3) { TResult result = default; arg2 = default; arg3 = default; using (var transaction = YourDbConnection.BeginTransaction()) { try { result = func(arg1, out arg2, out arg3); transaction.Commit(); } catch (Exception ex) { transaction.Rollback(); Console.WriteLine($"事务执行失败:{ex.Message}"); throw; } } return result; }
这个思路和你之前处理Action的逻辑完全一致,只是针对out参数做了必要的初始化和参数传递适配,完美解决带out参数方法的事务错误处理问题。
内容的提问来源于stack exchange,提问作者Maxim Chervyakov
相关产品推荐
相关产品推荐

