Исключение Entity Framework Optimistic Concurrency исключение не происходит - PullRequest
6 голосов
/ 16 марта 2011

У нас есть приложение ASP.Net MVC, которое использует EF4 в качестве слоя доступа к данным, и мы наблюдаем неожиданное поведение в отношении исключений OptimisitcConcurrencyException, когда мы думаем, что они должны быть.

Мы упростилипроблема в следующем коде ...

   using System.Linq;
    using Project.Model;

    namespace OptimisticConcurrency
    {
        class Program
        {
            static void Main()
            {
                Contact firstContact = null;
                using (var firstEntities = new ProjectEntities())
                {
                    firstContact = (from c in firstEntities.Contacts 
                       where c.LastName == "smith" select c).Single();
                }

                using (var secondEntities = new ProjectEntities())
                {
                    var secondContact = (from c in secondEntities.Contacts 
                       where c.LastName == "smith" select c).Single();

                    secondContact.Title = "a";
                    secondEntities.SaveChanges();
                }

                firstContact.Title = "b";

                using (var thirdEntities = new ProjectEntities())
                {
                    var thirdContact = (from c in thirdEntities.Contacts 
                       where c.LastName == "smith" select c).Single();

                    thirdContact.Title = firstContact.Title;

                    //EXPLICITLY SET VERSION HERE
                    thirdContact.Version = firstContact.Version;  

                    thirdEntities.SaveChanges();
                }
            }
        }
    }

Это довольно простая версия того, что происходит в нашем приложении MVC, но возникает та же проблема.

Когда мы вызываем SaveChanges для третьих объектов, я ожидаю исключения, и ничего не выдается.

Гораздо интереснее, что когда мы присоединяем SQL Profiler, мы видим, что в предложении where используется Version, но используется значение Version версии ThirdEntities (текущее в БД), а не значения firstEntitiesDESPITE он явно установлен непосредственно перед вызовом SaveChanges.SaveChanges сбрасывает версию, чтобы она была полученным значением, а не установленным значением.

В EDMX для версии установлено, что для StoreGeneratedPattern установлено значение Computed.

Кто-нибудь имеет представление о том, чтоздесь происходит?

1 Ответ

10 голосов
/ 16 марта 2011

Это проблема. Если для столбца установлено значение Computed, вы не сможете установить его значение в приложении (можно, но это значение не используется).

Edit:

Если вы загружаете сущность из базы данных, она по умолчанию отслеживается с контекстом. Контекст хранит свои исходные значения. Исходные значения, например, используются для отслеживания изменений снимка, но они также используются в качестве единственного действительного источника Computed свойств. Если вы устанавливаете свойство Computed в вашей сущности, значение не используется, а используется оригинальное значение. Обходной путь должен изменить исходное значение (прежде чем что-либо изменить):

using (var context = new TestEntities())
{
    var entityToUpdate = context.MyEntities.Single(e => e.Id == someId);
    entityToUpdate.Timestamp = entity.Timestamp;

    ObjectStateEntry entry = context.ObjectStateManager.GetObjectStateEntry(entityToUpdate);
    entry.ApplyOriginalValues(entityToUpdate);

    // set modified properties
    context.SaveChanges();
}

Редактировать 2:

Btw. как только вы действительно загрузили метку времени и ранее полученную метку времени, вы можете просто сравнить их в своем приложении вместо того, чтобы делать это в базе данных.

...