1

我有一个 Web 应用程序,用户通过单击“加入”按钮进行注册。网站上可以有这么多用户,这就是为什么为了保持我的数据库查询速度快;我选择不在数据库中添加 foriegnkey 约束(虽然它是关系数据库)。

现在发生的情况是,当具有相同 userId 的用户在两个不同的浏览器中打开应用程序并同时点击“加入”按钮时;将同一用户的两行添加到数据库中,这是错误的。

我必须阻止这种情况的想法是:

  1. 在存储过程和 SQL 事务隔离级别为 SERIALIZABLE 的事务中执行检查/插入逻辑;但是使用这种方法,即使两个不同的用户同时点击“JOIN”按钮,表格也会被锁定。
  2. 在 c# 中使用 lock 关键字并从其中执行检查/插入逻辑,但我相信如果来自两个浏览器的同一个用户他们将获得自己的锁并且仍然能够在数据库中有两个条目。同样对于不同的用户,它可能会产生问题,因为其他人的代码将等待第一个释放资源。
  3. 使用 EntityFramework 开箱即用支持的乐观并发,但我不确定它是否能解决我的问题。

你能帮我解决这个问题吗?

4

2 回答 2

2

您可以通过在用户名中创建唯一索引来轻松解决您的问题。所以,只有第一个会被保存。下一个将被报告为错误,因为它会破坏唯一索引。

其实应该是主键。

根据您的评论,您的桌子很大。因此,在整个表中查找一行而不在每个插入操作上使用索引肯定比在每个插入/删除/更新操作上更新索引要糟糕得多。你应该考虑这一点。

无论如何,解决如果已经存在则不插入值的问题的唯一方法是检查它。

乐观并发与此无关。乐观并发与读取数据、修改数据和保存更改有关,无需锁定表。乐观并发的作用可以在以下步骤中解释:

  1. 从数据库中读取原始行,没有任何锁或事务
  2. 该应用程序修改了原始行
  3. 当应用程序尝试保存更改时,它会检查数据库中的行是否与在步骤 1 中读取时完全相同。如果是,则保存更改。如果不是并发异常则抛出。

所以乐观并发对你没有帮助。

我坚持使用唯一索引,这是最安全、最简单且可能更有效的解决方案。

于 2015-12-16T11:49:10.227 回答
1

我会使用实体及其乐观并发。

它会将其包装在事务中并为您处理这些问题。请记住将标识和主键都放在表上。如果用户名必须是唯一的,则在表上添加唯一注释。

于 2015-12-16T13:45:33.073 回答