【问题标题】:Transactions: IsolationLevel set to Serializable - is this correct?事务:IsolationLevel 设置为 Serializable - 这是正确的吗?
【发布时间】:2017-05-24 11:55:25
【问题描述】:

能否请您帮我确认/取消使用 Serializable 隔离级别的疑虑。

我想确保为以下方法AddUserTournament 选择了正确的IsolationLevel。每当执行此事务时,我想 100% 确定 entity.seats 是最新的 - 防止任何其他事务同时添加用户。

我可以使用更宽松的IsolationLevel 来实现这一点,还是这似乎是正确的方法?

    public void AddUserTournament(Tournament entity, User user)
    {
        try
        {
            // Add the user to tournament. Do this with a snapshot-isolationlevel
            using (var transaction = _dbContext.Database.BeginTransaction(System.Data.IsolationLevel.Serializable))
            {
                try
                {
                    // Get all users and include their relations to tournament
                    entity =
                        _dbContext.Tournaments.Where(e => e.TournamentId == entity.TournamentId)
                            .Include(t => t.Users)
                            .FirstOrDefault();

                    // Get the user
                    user = _dbContext.Users.SingleOrDefault(e => e.UserId == user.UserId);

                    // Check if there are available seats in the tournament and if user exist amoung enrolled users
                    if (entity != null && entity.Seats > entity.Users.Count &&
                        entity.Users.All(e => user != null && e.UserId != user.UserId))
                    {

                        // Add user
                        entity?.Users.Add(user);

                        // Save changes
                        _dbContext.SaveChanges();

                        // Commit transaction
                        transaction.Commit();

                    }
                }
                catch (Exception)
                {
                    transaction.Rollback();
                }
            }
        }
        catch (DbEntityValidationException ex)
        {
            throw new FaultException(new FormattedDbEntityValidationException(ex).Message);
        }
    }

【问题讨论】:

  • EntityFramework 和 ADO.NET 是两种截然不同的技术,不要同时标记它们,就好像问题是指它们两者一样。根据您的代码,您使用的是 EntityFramework,因此 ADO.NET 完全无关
  • 也只是您的if 逻辑或分步执行...还传入实体然后覆盖...在我的书中不适合编程。

标签: c# entity-framework transactions transactionscope


【解决方案1】:

我知道这不是在回答你的问题,但我觉得我应该指出如何使它更具可读性。

只是展示了如何将“如果”重写为可读的内容。

//after you refactor it more you will see that this check is actually not needed.
if (entity != null)
{
    //Called entity but represents a Tournament
    //so the check is to see if the T has more seats than the current attending users
    if(entity.Seats.Count > entity.Users.Count)
    {
        //this was to check if the user is already in the attending users
        //if(entity.Users.All(e => user != null && e.UserId != user.UserId))

        var userInSeats = entity.Users.Where(x=>x.UserId == user.UserId).SingleOrDefualt();
        if(userInSeats == null )
        {
            // Add user
            entity.Users.Add(user);

            // Save changes
            _dbContext.SaveChanges();

            // Commit transaction
            transaction.Commit();
        }
    }
}

然后您会看到不需要空值检查,因为不应该在没有实体的情况下调用此方法...除非您使用您在此处不存在的泛型,否则我会称其为事物。

【讨论】:

    猜你喜欢
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 2013-02-13
    • 2014-06-03
    • 2016-02-09
    • 2011-04-25
    • 2016-03-25
    • 2021-10-22
    相关资源
    最近更新 更多