事务:IsolationLevel设置为Serializable - 这是正确的吗?

时间:2017-05-24 11:55:25

标签: c# entity-framework transactions transactionscope

请您帮我确认/不确认使用Serializable isolationlevel我的怀疑。

我想确保我为以下方法IsolationLevel选择了合适的AddUserTournament。每当执行此事务时,我希望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);
        }
    }

1 个答案:

答案 0 :(得分:0)

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

只是展示如何将'if'重写为可读的内容。

//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();
        }
    }
}

然后你会看到不需要进行空检查,因为这个方法不能在没有实体的情况下被调用...除非你使用的是你在这里使用的泛型,否则我会称之为它们。