EF по умолчанию использует оптимистическую модель параллелизма, что означает, что блокировки данных в источнике не удерживаются между моментом запроса данных и их обновлением. Поэтому он не проверяет наличие каких-либо конфликтов перед сохранением изменений в базе данных. При любых конфликтах возникает исключение OptimisticConcurrencyException (для получения дополнительной информации см. Как: управлять параллелизмом данных в контексте объекта ).
Хорошей практикой (когда вы делаете обновления в сценарии с высокой степенью параллелизма) довольно часто вызывать Обновить . В этом случае попробуйте использовать 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.
Решение очень простое, прикрепите ваши объекты до того, как выполнит какие-либо операции / запросы в вашем 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();
} * * тысяча двадцать-один
}