.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 块来捕获异常,保证代码的可靠性和可维护性。

.NET CORE 事务控制:如何避免 UserService 中的提前提交

原文地址: https://www.cveoy.top/t/topic/m8Jc 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录