【问题标题】:ASP.NET | Entity Framework, race conditionASP.NET |实体框架,竞争条件
【发布时间】:2016-08-05 01:20:04
【问题描述】:

我有一个允许用户喜欢项目的网络应用程序。每个项目都有他获得的总点赞数的属性。

当很多用户同时喜欢同一个项目时会出现此问题,然后我在 SQL 中收到不正确的值(由竞争条件引起)。

作为一个临时解决方案,我在控制器构造函数中创建了一个工作线程,用于处理队列,当接收到喜欢/不喜欢的项目请求时,我正在排队这个请求。工作线程正在对值进行出队并更新将 itemid 映射到 totalcount 的字典。

工作线程然后每隔一分钟用结果更新一次数据库。

附带问题:context.SaveChanges() 是否只保存对象中更改的内容?还是保存了对象的所有属性?

我感觉这个解决方案不是正确的,处理这种问题的最佳方法是什么?

【问题讨论】:

  • 您应该使用同步隔离级别(在 sql server 中称为 Serializable)来更新数据库。但是,您没有提及您的提供者,因此可能不可能(即,如果您使用 Ms Access)。
  • Does context.savechanges saves only what changed in an object? or it saves all of the properties of the objects - 这取决于。如果您将对象状态设置为已修改,则所有内容都会被保存,因为整个对象都被认为是脏的。如果您从上下文中获取现有对象并更新一个或多个属性,然后仅保存您更改的内容,则会将其保存回数据库
  • 嘿伊戈尔!说同步隔离级别是什么意思?我如何定义一个?我正在使用 Sql 数据库(托管在 azure 中)
  • 查看previous so answer 并查看 IsolationLevel 的链接。您可以使用可序列化的隔离级别将实体框架创建/调用包装在环境事务中。如果您正在处理增量更新(现有喜欢 +1)并在存储过程中处理更新,那么您应该做的是使用存储过程,并且该更新也应该包含在开始事务中。
  • 你能显示你的数据库架构吗?

标签: c# asp.net entity-framework


【解决方案1】:

您可以在读写发生时使用RepeatableRead事务范围女巫锁定数据:

using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.RepeatableRead }))
{
    ...
    context.SaveChanges();
    scope.Complete();
}

Entity Framework 跟踪实体字段更改并生成 sql 代码以仅更新已修改的那些。您可以明确指定您只想更新一个实体属性并忽略其他更改:

context.Entry(entity).State = EntityState.Unchanged;
context.Entry(entity)
        .Property(c => c.entityField).IsModified = true;

当您将对象附加到上下文中时,它也很有用:

context.Attach(entity);
context.Entry(entity)
        .Property(c => c.entityField).IsModified = true;

因为Attach 将实体及其属性放入Unchanged 状态的上下文中。

【讨论】:

    【解决方案2】:

    对于性能和并发问题,最好使用 ExecuteSqlCommand:

    string sql = "UPDATE Table SET LikeCount = LikeCount+1 WHERE Id={0}";
    using (var context = new BloggingContext()) 
    { 
        context.Database.ExecuteSqlCommand( sql, new SqlParameter("@Id", id)); 
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-09
      • 1970-01-01
      • 1970-01-01
      • 2022-01-23
      • 2020-08-01
      相关资源
      最近更新 更多