EF,默认情况下,使用了乐观并发模型,这意味着锁定未在当数据被查询,当它被更新的源举行的数据。因此,在保存对数据库的更改之前,不会检查是否存在任何冲突。对于任何冲突,都会引发OptimisticConcurrencyException(有关更多信息,请检查How to: Manage Data Concurrency in the Object Context)。
很好的做法(在高并发情况下进行更新时)经常调用Refresh。在这种情况下,尝试将它们发送到数据库中,这样使用前ClientWins的RefreshMode以刷新在客户端存储的值:
using (MiscEntities ctx = new MiscEntities())
{
try
{
var m = ctx.Rates.FirstOrDefault(m => m.UserId == UserIdGuid);
DataAccess.Rate oldDbRate = new DataAccess.Rate { RatingId = m.RatingId };
ctx.AttachTo("Rates", dbRate);
dbRate.Rating = Rating;
dbRate.DateLastModified = DateTime.Now;
ctx.SaveChanges();
}
catch (OptimisticConcurrencyException)
{
ctx.Refresh(RefreshMode.ClientWins, dbRate);
ctx.SaveChanges();
}
}
编辑:更多的阅读和重新阅读该错误消息后它是有道理的,你不能附加一个对象到一个ObjectContext对象已经被ObjectStateManager缓存了。
该解决方案非常简单,在您的ObjectContext中执行任何操作/查询之前,将您的对象附加到之前。这可以防止任何双重跟踪请求。如果ObjectContext稍后需要您的实体,它将检索您之前附加的实例,并且您可以轻松前往。看看这个代码,看看它是否有助于(抱歉没有Visual Studio 2010中,现在打开)
using (MiscEntities ctx = new MiscEntities())
{
try
{
ctx.AttachTo("Rates", dbRates);
var m = ctx.Rates.FirstOrDefault(m => m.UserId == UserIdGuid);
DataAccess.Rate oldDbRate = new DataAccess.Rate { RatingId = m.RatingId };
dbRate.Rating = Rating;
dbRate.DateLastModified = DateTime.Now;
ctx.SaveChanges();
}
catch (OptimisticConcurrencyException)
{
ctx.Refresh(RefreshMode.ClientWins, dbRate);
ctx.SaveChanges();
}
}
谢谢,但它未能在AttachTo方法。它说“ObjectStateManager中已经存在具有相同键的对象,ObjectStateManager不能使用同一个键跟踪多个对象。”任何想法如何解决? – obautista 2011-01-26 06:16:08