2011-09-01 2 views
2

У меня есть проект, в котором я определил в EF Employer как производный класс User. В моем процессе я создаю пользователя, не зная, станет ли он в конечном итоге работодателем (или другими пользователями), а затем мне нужно его преобразовать. Сначала я попробовал (Intellisense указано явное преобразование существует):Downcasting с 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, который не предлагает .Cast<>, поэтому я использовал прямой запрос, чтобы туда добраться ... но я все равно получаю исключение динамических прокси-объектов.

так что мой вопрос: как я могу опуститься, когда объект имеет постоянство через EF?

+0

является частью 'Employer' вашей модели EF?если вы правильно наследуете наследование как 'TPH' или' TPC', тогда EF создаст правильный прокси-класс подкатегория – Eranga

+0

@Eranga, да 'Employer' является частью EF-модели. И я использую TPT, поэтому у меня есть таблица под названием «Пользователи» и одна называется «Users_Employer» – ekkis

ответ

6

Невозможно. Вы всегда должны использовать конечный тип. Создав его как User, EF никогда не позволит вам изменить его на производный тип сущности.

КПП. это также невозможно с объектно-ориентированным подходом. Вы не можете использовать экземпляр родительского класса для экземпляра производного класса (если только он не является экземпляром производного класса) - он будет генерировать исключение во время выполнения. Очень простой пример, чтобы воспроизвести проблему:

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 (и); db.Employers.Add (е); db.SaveChanges() '? – ekkis

+1

Да, это именно то, что вам нужно сделать, чтобы заставить его работать. –

+0

спасибо Ladislav. это кажется чрезмерно карательным, если вы считаете, что вам нужна глубокая копия на объекте, который может иметь всевозможные зарубежные ссылки ... иметь все, что нужно от базы данных, удалять все и воссоздавать, когда действительно, все, что мне нужно, сделать пару записей в моей таблице Users_Employer, но ваше решение работает. конечно, теперь у меня другая проблема ... см. http://stackoverflow.com/questions/7276507/serializable-classes-and-dynamic-proxies-in-ef-how – ekkis

0

Предположим, что ваш объект Employer имеет только свойства с нулевым значением, тогда можно перейти к таблице в базе данных и изменить Дискриминатор от пользователя к работодателю. Все отношения будут сохранены. А также можно сделать обратное.