2016-08-04 56 views
4

我有一个Web应用程序,允许用户喜欢项目。每个项目都有他喜欢的总喜欢的属性。ASP.NET |实体框架,竞争条件

的问题,当在同一时间很多用户喜欢同样的项目,然后我在SQL接受不正确的值(由竞争状态)发生。

作为一个临时的解决方案,我已经创造了控制器的构造函数,对队列的作品,当喜欢/不喜欢请求的项目被接受,我排队申请工作线程。工作者线程正在取值并更新将itemid映射到totalcount的字典。

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

方问题:确实context.SaveChanges()保存在一个对象只发生了什么变化?还是保存对象的所有属性?

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

+1

应当更新使用syncronized隔离级别的数据库(SQL Server中的所谓的序列化)。但是,您并未提及您的提供商,因此可能无法实现(例如,如果您使用Ms Access)。 – Igor

+1

'context.savechanges是否仅保存对象中更改的内容?或者它保存了对象的所有属性 - 取决于它。如果将对象状态设置为已修改,则会保存所有内容,因为整个对象都被认为是脏的。如果从上下文中获取现有对象并更新一个或多个属性,然后仅保存更改的内容将保存回数据库 – Igor

+0

嘿伊戈尔!说同步隔离级别时,你是什么意思?我如何定义一个?我使用SQL数据库(在蔚蓝的托管) –

回答

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状态的上下文。

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)); 
}