网络游戏...玩家需要建立团队,稍后再与之作战。我想在玩家的帐户下将建立的团队保留在数据库中。
但是,我想限制一个球员可以存储多少支球队。如何实现呢?
public const MaxTeams = 10;
[Authorize] public async Task AddTeam(string teamSerialized)
{
var previousTeamsNo = await dbContext.SavedTeams.CountAsync(
t => t.playerId == Context.UserIndentifier
);
if (previousTeamsNo < MaxTeams) {
var team = new SavedTeam(teamSerialized);
if (team.isValid) {
dbContext.Add(team);
await dbContext.SaveChangesAsync();
}
}
}
虽然上面的代码可能很简单,但恐怕它也是无效的。线程1计数用户previousTeamsNo
的{{1}};它等于JohnDoe
,因此线程1进入最外面的9
的主体。线程2计数同一用户的if
;由于T1尚未添加新团队,因此T2仍然看到previousTeamsNo
等于previousTeamsNo
并进入最外面的9
的正文。两个线程完成后,if
保存了JohnDoe
个团队,这是我要禁止的。
那该如何解决?
================
好吧,尽管我不确定,但我有一个主意。我了解事物的方式-如果我错了,请纠正我-我需要启动提供最高隔离级别-Serializable的事务,以确保既不会使用11
也不插入或删除行指向playerId
的ID,而另一个线程处于其事务中间。实体框架核心seems to allow this。但是,我不确定我是否理解上一句话中链接到的文档内容:
可序列化。在数据集上放置了范围锁,以防止其他用户在事务完成之前更新或向数据集中插入行。
这意味着在执行JohnDoe
查询时锁定了什么?仅这些行(当前行和将来行)的CountAsync
外键指向playerId
的ID?还是整个JohnDoe
表都被锁定,有效地禁用了并发性?这是很难接受的,不是吗?
最后,在SavedTeams
方法中使用Serializable
隔离级别是否有效?还是在async
事务中使用CountAsync
和SaveChangesAsync
是否有效?我的意思是,可序列化本质上是充当锁-和isn't mixing async
and locks a recipe for deadlocks?
我如何正确实现所需的条件?