2012-02-21 2 views
1

엔티티의 몇 가지 속성 만 변경할 수있는 경우 코드에 시나리오가 있습니다.Entity Framework에서 새 인스턴스를 반환하도록 지정

public void SaveCustomer(Customer customer) 
{ 
    var originalCustomer = dbContext.GetCustomerById(customer.Id); 

    if (customer.Name != originalCustomer.Name) 
    { 
     throw new Exception("Customer name may not be changed."); 
    } 

    originalCustomer.Address = customer.Address; 
    originalCustomer.City = customer.City; 

    dbContext.SaveChanges(); 
} 

이 코드의 문제는 dbContext.GetCustomerById에 대한 호출은 항상하지 않는 나에게 Customer 클래스의 새로운 인스턴스를 제공한다는 것입니다 : 그 보장하기 위해, 우리는 다음과 유사한 코드가 있습니다. 고객이 이미 데이터베이스에서 가져온 경우 Entity Framework는 인스턴스를 메모리에 유지하고 이후의 모든 호출에서 인스턴스를 반환합니다.

이렇게하면 실제 문제가 발생합니다. customeroriginalCustomer은 같은 인스턴스를 참조 할 수 있습니다. 이 경우 customer.NameoriginalCustomer.Name과 같을 것이며 데이터베이스와 다른지 여부를 감지 할 수 없습니다.

identitymap 디자인 패턴 때문에 대부분의 다른 ORM에도 같은 문제가 있다고 생각됩니다.

어떻게 해결할 수 있습니까? 나는 어쨌든 EF가 항상 고객 클래스의 새로운 인스턴스를 제공하도록 강제 할 수 있습니까?

대신 코드를 리팩터링해야합니까? 누구든지이 시나리오에 적합한 디자인 패턴을 알고 있습니까?

+0

경우'에서 오는 GetCustomerById'는 무엇입니까? 또한, 귀하의 컨텍스트의 평생은 무엇입니까? – ken2k

+0

아, 죄송합니다. GetCustomerById는 DbSet .Find()에 대한 래퍼 메서드입니다. 수명은 HTTP 요청 당입니다. – jhu

+0

'Name'을 바꾸고 싶지 않다면 상위 계층 코드가'Customer' 엔티티 (= Name 클래스는'Name'이 읽기 전용이 될 새로운 클래스 생성)와 함께 작동하지 않게하거나 설정자를 숨길 수 있습니다. –

답변

1

컨텍스트에서 엔티티를 분리하면이 컨텍스트에 대한 참조 (identitymap 동작)가 제거됩니다. 그래서, 당신의 방법으로 고객에게 전달하기 전에 당신을 분리 할 수 ​​있습니다 :

yourContext.Detach(customer); 
+1

이것은 기술적으로 정답입니다. 데이터베이스에서 신선한 인스턴스를 가져 오려면 먼저 컨텍스트에서 이전 인스턴스를 분리해야합니다. –

관련 문제