2011-09-01 6 views
2

나는 EF에서 User의 파생 클래스로 Employer으로 정의한 프로젝트를 가지고 있습니다. 내 프로세스에서는 결국 사용자 (또는 다른 종류의 사용자)가 될지 여부를 모른 채 사용자를 생성하고 나중에 변환해야합니다. 처음에는 (인텔리가 명시 적 변환이 존재 표시) 시도 :Entity Framework로 다운 캐스팅

Employer e = (Employer) GetUser(); 

하지만 런타임에 내가 가지고 :

Unable to cast object of type 'System.Data.Entity.DynamicProxies.User_7B...0D' to type 'Employer'. 

은 그래서 컨버터 쓰려고했습니다 :

public partial class User 
{ 
    public static explicit operator Employer(User u) 
    { 

을하지만 오류 메시지 :

Error 21 'User.explicit operator Employer(User)': user-defined 
conversions to or from a derived class are not allowed 
C:\Users\..\Documents\Visual Studio 2010\Projects\..\Website\Models\EF.Custom.cs 

괜찮아. 나는 다음과 같은 Employer의 생성자를 오버로드 :

public partial class Employer 
{ 
    public Employer(User u) 
    { 
     this.Id = u.Id; 
     this.Claims = u.Claims; 
     // etc. 
    } 
} 

을하고 난 후 바로 할 수있는 생각 :

Employer e = new Employer(GetUser()); 

하지만 난 그것을 실행할 때 오류 얻을 :

System.InvalidOperationException was unhandled by user code 
    Message=Conflicting changes to the role 'User' of the 
    relationship 'EF.ClaimUser' have been detected. 
    Source=System.Data.Entity 
    StackTrace: 
     [...] 
     at Controllers.AuthController.Register(String Company, String GivenName, 
     String Surname, String Title, String Department) in C:\Users\..\Documents\ 
     Visual Studio 2010\Projects\..\Website\Controllers\AuthController.cs:line 

등을 최후의 수단으로이 글을 써 보았습니다.

 Employer e = Auth.Claims("id") 
      .Where(x => x.Value == Auth.NameIdentifier()) 
      .Select(x => x.User) 
      .Cast<Employer>() 
      .Single(); 

... GetUser()는 을 제공하지 않는 User 유형의 객체를 반환하므로 거기에 직접 쿼리를 사용했지만 동적 프록시 객체 예외는 여전히 발생합니다.

내 질문은 : 개체가 EF를 통해 지속성을 유지할 때 어떻게 다운 캐스트 할 수 있습니까?

+0

은 EF 모델의 '고용주'부분입니까?상속을'TPH' 나'TPC'로 정확하게 매핑했다면 EF는 올바른 하위 클래스 프록시 인 – Eranga

+0

@Eranga를 인스턴스화합니다. 예'Employer'는 EF 모델의 일부입니다. 그리고 나는 TPT를 사용하여'Users'라는 테이블과'Users_Employer'라는 테이블을 가지고 있습니다. – ekkis

답변

6

불가능합니다. 항상 최종 형식을 사용해야합니다. 일단 User으로 생성하면 EF는이를 파생 된 엔티티 유형으로 변경할 수 없습니다.

btw. 객체 지향 접근법으로도 불가능합니다. 부모 클래스의 인스턴스를 파생 클래스의 인스턴스에 캐스트 할 수는 없습니다 (파생 클래스의 인스턴스가 아닌 경우). 런타임에 예외가 발생합니다. 내부적으로 파생 클래스의 새 인스턴스를 생성하고 그 새로운 파생 된 하나에 이전 부모 인스턴스에서 모든 필드를 복사 것이다 오버라이드 (override)되어 변환 연산자를 할

class X { } 

class Y : X { } 

class Program 
{ 
    static void Main(string[] args) 
    { 
     X x1 = new Y(); 
     Y y1 = (Y)x1; // Works 

     X x2 = new X(); 
     Y y2 = (Y)x2; // InvalidCastException 
    } 
} 

유일한 방법 : 아주 간단한 예제 문제를 재현합니다.

엔티티 프레임 워크에서 정확히 동일한 접근 방식이 필요합니다. User 엔터티로 시작한 후 Employer 엔터티로 승격하려면 이전 사용자를 삭제하고 새로 Employer을 만들어야합니다.

+0

하지만 변환 연산자를 덮어 쓰려고했습니다 (위의 오류 참조). 내가 언급 한 복사본으로 새로운 객체를 만들려고 시도했지만 실패했다. (위에서 설명한대로) 문제가 발생했다. 당신은 내가 다음과 같은 것을 할 필요가 있다고 제안하고 있는가? User u = db.Users.Find (...); 고용주 e = 새 고용주 (u); db.Users.Remove (u); db.Employers.Add (e); db.SaveChanges()'? – ekkis

+1

예. 제대로 작동하도록하려면 정확하게해야합니다. –

+0

Ladislav에 감사드립니다. 그것은 모든 종류의 외국 참조를 가질 수 개체에 깊은 복사본에 대한 필요성을 고려하는 경우 접근법을 과도하게 처벌하는 것 ... 데이터베이스에서 모든 것을 움켜 잡고, 모든 것을 삭제하고, 그것을 다시 만들 때, 정말 필요한 모든 것은 내 Users_Employer 테이블에 몇 가지 항목을 만들지 만 솔루션이 작동합니다. 물론 지금은 다른 문제가 있습니다 ... 참조 : http://stackoverflow.com/questions/7276507/serializable-classes-and-dynamic-proxies-in-ef-how – ekkis

0

Employer 엔티티에 nullable 속성 만 있으면 데이터베이스의 테이블로 이동하여 Discriminator를 User에서 Employer로 변경할 수 있습니다. 모든 관계가 유지됩니다. 또한 그 반대도 할 수 있습니다.