Даункинг с Entity Framework - PullRequest
       38

Даункинг с Entity Framework

2 голосов
/ 01 сентября 2011

У меня есть проект, в котором я определил в EF Employer как производный класс User.В моем процессе я создаю пользователя, не зная, будет ли он в конечном итоге работодателем (или другими пользователями), и позже мне нужно его преобразовать.Сначала я попытался (Intellisense указал, что явное преобразование существует):

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?

Ответы [ 2 ]

6 голосов
/ 01 сентября 2011

Это невозможно.Вы всегда должны использовать окончательный тип.Как только вы создадите его как 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
    }
}

Единственный способ сделать это - переопределить оператор преобразования, который внутренне создаст новый экземпляр производного класса и скопирует все поля из старого родительского экземпляра в этот новый производныйone.

Точно такой же подход необходим для структуры сущностей.Если вы начали с сущности User и теперь хотите повысить ее до сущности Employer, вы должны удалить старого пользователя и создать нового Employer.

0 голосов
/ 22 февраля 2014

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

...