5

EF4를 데이터 액세스 계층으로 사용하는 ASP.Net MVC 응용 프로그램이 있으며 예상대로 작동하지 않을 것으로 예상되는 경우 OptimisitcConcurrencyExceptions와 관련하여 예기치 않은 동작이 나타납니다. 우리는 다음과 같은 코드를 아래로 문제를 단순화Entity Framework 낙관적 동시성 예외가 발생하지 않습니다.

...

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 응용 프로그램에서 어떤 일이 일어나는지 오히려 간단한 버전입니다,하지만 같은 문제가 발생합니다.

thirdEntities에서 SaveChanges를 호출 할 때 예외가 발생하고 아무 것도 throw되지 않습니다.

훨씬 더 흥미롭게도 우리는 SQL 프로파일 러를 부착 할 때 버전이 where 절에서 사용되고 있지만 사용중인 firstEntities 값이 아닌 thirdEntities 버전 값 (현재 DB의 값)이 DESPITE임을 확인합니다 SaveChanges가 호출되기 직전에 명시 적으로 설정됩니다. SaveChanges는 버전을 검색 값으로 설정 값이 아닌 재설정합니다.

EDMX에서 버전은 StoreGeneratedPattern이 Computed로 설정됩니다.

누구나 여기서 무슨 일이 벌어지고 있는지 알 수 있습니까?

답변

9

이것은 문제입니다. 열이 Computed으로 설정되면 응용 프로그램에서 해당 값을 설정할 수 없지만 값은 사용되지 않습니다.

편집 : 당신이 데이터베이스에서 개체를로드하는 경우는 문맥에 추적 기본적으로

입니다. 컨텍스트는 원래 값을 저장합니다. 원래 값은 예를 들어 스냅 샷 변경 내용 추적에 사용되지만 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는

. 실제로 타임 스탬프와 이전에 검색 한 타임 스탬프를 모두로드 한 후에는 데이터베이스에서 수행하는 대신 간단히 compare them in your application을 사용할 수 있습니다.

+1

버전 열을 StoreGeneratedPattern = None으로 설정하면 데이터베이스의 타임 스탬프 열을 업데이트 할 수 없다는 예외가 발생합니다. –

+0

예이 동작은 완전히 작동하지 않습니다. 저녁에 해결 방법 하나를 시도하고 알려 드리겠습니다. –

관련 문제