C# 实体框架-事务范围悲观锁定

C# 实体框架-事务范围悲观锁定,c#,entity-framework,entity-framework-6,transactionscope,pessimistic-locking,C#,Entity Framework,Entity Framework 6,Transactionscope,Pessimistic Locking,我一直在尝试使用事务作用域实现EF上下文的悲观锁定 型号: 现在我正在寻求下面描述的行为应该有效的认可,如果不行,我很高兴听到反馈或建议,使之成为可能 预期行为: 假设我们有3个线程:A-首先调用Join();B-调用列表();C-第二次调用Join() 房间,容量是1 这就是我期望发生的事情:A调用Join()。方法检查它是否可以加入-看起来是的,所以它进入TransactionScope。此时,B调用List()-因为A尚未完成Join(),B认为房间中没有用户。这里重要的一点是,B不会等到

我一直在尝试使用事务作用域实现EF上下文的悲观锁定

型号:

现在我正在寻求下面描述的行为应该有效的认可,如果不行,我很高兴听到反馈或建议,使之成为可能

预期行为:

假设我们有3个线程:A-首先调用Join();B-调用列表();C-第二次调用Join()

房间,容量是1

这就是我期望发生的事情:A调用Join()。方法检查它是否可以加入-看起来是的,所以它进入TransactionScope。此时,B调用List()-因为A尚未完成Join(),B认为房间中没有用户。这里重要的一点是,B不会等到A完成事务,而是会访问最后提交的row版本。现在,C正在调用Join()。因为A仍在处理事务,所以C对room的初始测试成功,所以它也进入了TransactionScope但由于A尚未完成,C现在应该等待它。A完成事务后,房间中的用户数量现在是1。A解锁事务,C进入它。它再次获取房间模型,测试容量只是为了发现它不能加入,所以抛出异常

我的东西可能坏了:

我对IsolationLevel.RepeatableRead没有把握。在文档中,据说易失性数据可以在事务期间读取,但不能修改。可以在事务处理期间添加新数据。。一方面,我希望这将允许List()方法按原样读取行,而不会等待TransactionScope完成。此外,它应该只锁定行,而不是表,所以可以添加新房间。但我担心当A仍在运行时,它不会阻止锁C的TransactionScope。最后,我不确定“在事务期间可以读取但不能修改易失性数据”是否也适用于TransactionScope

总而言之:请告诉我我的代码是否会按预期运行,如果不会,我应该做些什么调整来实现这一点?提前谢谢

User

Room
    ICollection<User> Users
    int Capacity
public void List()
{
    using(var context = new MyDBContext())
    {
        // Let's pretend that this method grabs list of users from room and creates list of their names and then dumbs them
        foreach(var item in context.Rooms.First().GetUserNames()) 
            Console.WriteLine(item);
    }
}

public void Join()
{
    using(var context = new MyDBContext())
    {
        var room = context.Rooms.First();
        if(room.Users.Count >= room.Capacity)
            throw new Exception("No room");

        using(var transaction = new Transaction(
                TransactionScopeOption.Required,
                new TransactionOptions
                {
                    IsolationLevel = IsolationLevel.RepeatableRead
                }
            ))
        {
            room = context.Rooms.First(); // Fetch again to get latest version

            if(room.Users.Count >= room.Capacity)
                throw new Exception("No room");

            room.Users.Add(CurrentUser);

            context.SaveChanges();
            transaction.Complete();
        }
    }
}