简体   繁体   中英

optimisticconcurrencyexception was caught when updating entity relation using stub entities

This code is giving me optimisticconcurrencyexception was caught. I am simply using a Stub Entity to get an existing record and trying to update a couple values. I am not sure how to resolve the exception. Any help is very much appreciated:

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

EF, by default, uses an optimistic concurrency model, meaning that locks are not held on data in the source between when the data is queried and when it is updated. So it doesn't check for any conflicts before saving changes to the database. With any conflicts an OptimisticConcurrencyException is raised (for more information check out How to: Manage Data Concurrency in the Object Context ).

It's good practice (when you make updates in a high concurrency scenario) to call Refresh quite often. In this case try using a RefreshMode of ClientWins to to refresh the values in the client store before sending them to the database, like this:

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

EDIT: After more reading, and re-reading that error message it makes sense, you cannot attach an object to an ObjectContext is that object has already that has already been cached by the ObjectStateManager.

The solution is real simple, attach your objects before doing any operations/query in your ObjectContext. This allows you to prevent any double-tracking requests. If the ObjectContext needs your Entity later, it will retrieve the instance you attached before and you're good to go. Take a look at this code and see if it helps (Sorry don't have Visual Studio 2010 opened right now)

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

}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM