Поддерживается ли наследование навигационных свойств? - PullRequest
3 голосов
/ 10 марта 2012

Не удается найти релевантные результаты поиска ...

Для данной модели:

public abstract class A
{
    public int ID { get; set; }
    public int CustomerID { get; set; }
    public virtual Customer Customer { get; set; }
}

public class B : A
{
}

public class C : A
{
}

public class Customer
{
    public int ID { get; set; }
    public virtual ICollection<B> Bs { get; set; }
    public virtual ICollection<C> Cs { get; set; }
}

При такой конфигурации:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<A>().ToTable("As");
    modelBuilder.Entity<B>().ToTable("Bs");
    modelBuilder.Entity<C>().ToTable("Cs");

    base.OnModelCreating(modelBuilder);
}

Я получаю этот результат в БД:

Database

Вопрос:

Isнаследование свойств навигации не поддерживается?Если я добавлю public string SomeSharedProperty { get; set; } к A, то, как и следовало ожидать, столбец для этого свойства будет показан только в таблице As.

Какова причина для столбца Customer_ID в * 1030?* а Cs стол?Есть ли способ сказать EF не отображать это унаследованное свойство?

Спасибо!

1 Ответ

3 голосов
/ 10 марта 2012

Во-первых, наследование поддерживается.Но в данном конкретном случае это выглядит не так, как вы ожидаете.

Поскольку реляционные БД не поддерживают наследование, как мы знаем из объектно-ориентированного программирования, для того, чтобы это произошло, должно быть какое-то преобразование.

Вот серия постов в блоге, подробно освещающая проблему:

Он также пытается дать рекомендации, когда использовать какую из стратегий.

ОБНОВЛЕНИЕ
Видимо, это сложнее, чем казалось на первый взгляд.То, что вы видите, наиболее вероятно из-за циклической ссылки: A -> B -> Customer -> Bs.

Столбцы CustomerID Bs / C НЕ являются унаследованными из таблицы As.Фактически это представление свойств отношений, указанных в классе Customer:

public virtual ICollection<B> Bs { get; set; }

, в результате столбец обнуляется CustomerID в таблице B.

public virtual ICollection<C> Cs { get; set; }

приводит к появлению столбца , обнуляемого CustomerID, в таблице C.

Таким образом, эти столбцы, допускающие обнуление, используются для представления отношения Customer -> Bs и Customer -> Cs.Их внешний вид не имеет ничего общего со свойством Customer класса A.

Вы можете легко проверить это, удалив свойства навигации класса клиента.Тогда вы получите ожидаемый результат: столбец CustomerID в таблице A и столбец CustomerID в таблице B / C.

Поэтому, чтобы решить эту проблему, вам нужно специально указать EF, какразрешить круговую ссылку.Не уверен, что это возможно, хотя, боюсь, вам нужно будет пропустить свойства Bs / Cs в Customer и написать вместо этого запрос LINQ для получения информации.

Если вам нужны эти свойства вCustomer класс, который вы можете сделать, выглядит примерно так:

public class Customer
{
    public int ID { get; set; }

    // this is necessary to have access to the related Bs/Cs
    // also it cant be private otherwise EF will not overload it properly
    public virtual ICollection<A> As { get; set; }

    public IEnumerable<B> Bs { get { return this.As.OfType<B>(); } }
    public IEnumerable<C> Cs { get { return this.As.OfType<C>(); } }
}
...