ASP.NET |实体框架,竞争条件

时间:2016-08-04 15:57:25

标签: c# asp.net entity-framework

我有一个Web应用程序,允许用户喜欢项目。每件物品都有他喜欢的总物品。

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

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

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

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

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

2 个答案:

答案 0 :(得分:1)

发生读写操作时,可以使用RepeatableRead事务范围锁定数据:

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

实体框架跟踪实体字段更改并生成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状态的上下文中。

答案 1 :(得分:0)

表示性能和并发问题比使用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)); 
}