使用存根实体更新实体关系时捕获到optimisticconcurrencyexception

时间:2011-01-25 02:17:01

标签: c# entity-framework

这段代码给了我optimisticconcurrencyexception被抓住了。我只是使用Stub Entity来获取现有记录并尝试更新几个值。我不知道如何解决这个异常。非常感谢任何帮助:

using (MiscEntities ctx = new MiscEntities())  
{  
    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();  
}  

1 个答案:

答案 0 :(得分:2)

默认情况下,EF使用乐观并发模型,这意味着在查询数据和更新数据之间,源中的数据不会保留锁。因此,在保存对数据库的更改之前,它不会检查是否存在任何冲突。任何冲突都会引发OptimisticConcurrencyException(有关更多信息,请查看How to: Manage Data Concurrency in the Object Context)。

这是一种很好的做法(当您在高并发方案中进行更新时)经常调用Refresh。在这种情况下,尝试使用RefreshMode ClientWins来刷新客户端存储中的值,然后再将它们发送到数据库,如下所示:

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缓存。 / p>

解决方案非常简单,在之前附加对象在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();

}
}