问题
Having difficulty finding relevant search results...
Given this model:
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; }
}
With this configuration:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<A>().ToTable("As");
modelBuilder.Entity<B>().ToTable("Bs");
modelBuilder.Entity<C>().ToTable("Cs");
base.OnModelCreating(modelBuilder);
}
I get this result in the DB:

Question:
Is inheritance of navigation properties not supported? If I add public string SomeSharedProperty { get; set; }
to A
then as I would expect the column for that property only showed up in the As
table.
What reason is there for the Customer_ID
column in the Bs
and Cs
table? Is there any way to tell EF to not map that inherited property?
Thanks!
回答1:
First off, inheritance is supported. But it seems in this specific instance not as you would expect.
Since Relational DBs do not support inheritance as we know it from object oriented programming there has to be some kind of transformation in order to make it happen.
Here is a series of blog post covering the issue in detail:
- Table per hierarchy
- Table per type
- Table per class
It also tries to give guidelines when to use which of the strategies.
UPDATE
Apparently this is more tricky than it seemed at first glance. What you see is most likely due to a circular reference: A -> B -> Customer -> Bs
.
The CustomerID
columns of Bs/Cs are NOT the inherited ones from the As Table. It is in fact the representation of the relation properties specified on the Customer
class:
public virtual ICollection<B> Bs { get; set; }
results in a nullable CustomerID
column on table B.
public virtual ICollection<C> Cs { get; set; }
results in a nullable CustomerID
column on table C.
So those nullable columns are used to represent the relation Customer -> Bs
and Customer -> Cs
. Their appearance has nothing to do with the Customer
property on the A
class.
You can easily check this by removing the navigation properties of the customer class. Then the result is what you would expect: A CustomerID
column on the A table and no CustomerID
column on B / C Table.
So in order to solve this you need to specifically tell EF how to resolve the circular reference. Not sure this is possible though, I'm afraid you will need to omit the Bs/Cs properties on the Customer
and write a LINQ query instead to retrieve the info.
If you need those properties on the Customer
class you can do is something like this:
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>(); } }
}
来源:https://stackoverflow.com/questions/9648109/is-inheritance-of-navigation-properties-supported