.NET CORE 事务控制:如何避免 UserService 中的提前提交
.NET CORE 事务控制:如何避免 UserService 中的提前提交
在 .NET CORE 开发中,我们经常会遇到需要进行数据库操作的情况。为了保证数据一致性,我们通常会使用事务来确保多个操作的原子性。然而,有时我们会遇到在 UserService 中事务过早提交的问题,导致数据不一致。
问题描述
以下代码展示了一个典型的场景,在 OrderService 中进行订单更新操作,并调用 UserService 更新用户订单记录。问题在于 UserService 内部使用了事务,导致事务过早提交,无法保证整个操作的原子性。
public class UserAppService : IUserAppService
{
private IUserService userService{get;set;}
public void UpdateOrderRecord(Order order)
{
userService.UpdateOrderRecord(order);
}
}
public class OrderAppService : IOrderAppService
{
private IOrderService OrderService{get;set;}
public void UpdateOrder(OrderDto order)
{
OrderService.Update(order);
}
}
public class OrderService : IOrderService
{
private DbContext dbContext { get; set; }
private IUserService userService { get; set; }
public void Update(OrderDto orderDto)
{
using (var trans = dbContext.Database.BeginTransaction())
{
Order order = dbContext.Order.First();
order.Update(orderDto);
userService.UpdateOrderRecord(order);
trans.Commit();
}
}
}
public class UserService : IUserService
{
private DbContext dbContext { get; set; }
public void UpdateOrderRecord(Order order)
{
using (var trans = dbContext.Database.BeginTransaction())
{
var user = dbContext.User.First();
user.UpdateOrderRecord(order);
dbContext.SaveChanges();
trans.Commit();
}
}
}
pulic class UserScoreService : IUserService
{
private DbContext dbContext { get; set; }
public void AddScore(User user)
{
dbContext.UserScore.Add(new UserScore(user));
dbContext.SaveChanges();
}
}
解决方案
为了解决这个问题,我们可以将事务控制权交给上层调用方法,让 UserService 和 UserScoreService 不再使用事务。修改后的代码如下:
public class UserAppService : IUserAppService
{
private IUserService userService{get;set;}
private IUserScoreService userScoreService{get;set;}
public void UpdateOrderRecord(Order order)
{
using (var trans = dbContext.Database.BeginTransaction())
{
try
{
userService.UpdateOrderRecord(order);
userScoreService.AddScore(order.User);
trans.Commit();
}
catch (Exception ex)
{
trans.Rollback();
throw ex;
}
}
}
}
public class OrderAppService : IOrderAppService
{
private IOrderService OrderService{get;set;}
public void UpdateOrder(OrderDto order)
{
using (var trans = dbContext.Database.BeginTransaction())
{
try
{
OrderService.Update(order);
trans.Commit();
}
catch (Exception ex)
{
trans.Rollback();
throw ex;
}
}
}
}
public class OrderService : IOrderService
{
private DbContext dbContext { get; set; }
public void Update(OrderDto orderDto)
{
Order order = dbContext.Order.First();
order.Update(orderDto);
userService.UpdateOrderRecord(order);
}
}
public class UserService : IUserService
{
private DbContext dbContext { get; set; }
public void UpdateOrderRecord(Order order)
{
var user = dbContext.User.First();
user.UpdateOrderRecord(order);
dbContext.SaveChanges();
}
}
public class UserScoreService : IUserService
{
private DbContext dbContext { get; set; }
public void AddScore(User user)
{
dbContext.UserScore.Add(new UserScore(user));
dbContext.SaveChanges();
}
}
解释
在修改后的代码中,我们使用了一个 try-catch 块来捕获异常,并在异常发生时回滚事务。这样,我们可以确保所有操作要么全部成功,要么全部失败,保证数据的一致性。
总结
通过将事务控制权交给上层调用方法,我们可以有效地避免 UserService 中的事务过早提交,保证数据的一致性。在设计代码时,我们应该合理地划分事务范围,并使用 try-catch 块来捕获异常,保证代码的可靠性和可维护性。
原文地址: https://www.cveoy.top/t/topic/m8Jc 著作权归作者所有。请勿转载和采集!