是否支持导航属性的继承? [英] Is inheritance of navigation properties supported?

查看:112
本文介绍了是否支持导航属性的继承?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

难以找到相关的搜索结果...



给定此模型:

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

public class B:A
{
}

public class C:A
{
}

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

使用此配置:

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

base.OnModelCreating(modelBuilder);
}

我在DB中得到这个结果: / p>



问题:



导航属性的继承不受支持?如果我添加 public string SomeSharedProperty {get;组; } to A 然后,我希望该属性的列仅在中显示为表。



Bs 中的 Customer_ID 列有什么原因? / code>和 Cs 表?有没有办法告诉EF不映射继承的财产?



谢谢!

解决方案

首先,继承是支持的。但是,在这个具体的实例中,似乎并不如你所期望的那样。



由于关系数据库不支持继承,因为我们从面向对象的编程中知道它们必须有某种为了使其发生变化。



以下是一系列详细的博客文章:





它还会尝试给出使用哪些策略的指导。



更新

显然这比乍看起来更棘手。你看到的最有可能是由于循环引用: A - > B - >客户 - > Bs



Bs / Cs中的 CustomerID 列不是继承的作为表。它实际上是在客户类中指定的关系属性的表示:

  public virtual ICollection< B> Bs {get;组; 

导致可空 CustomerID 列在表B上。

  public virtual ICollection< C> Cs {get;组; 

导致可空 CustomerID 列表C。



所以这些可空的列用于表示关系 Customer - > Bs 客户 - > CS 。它们的外观与 A 类中的客户属性无关。



您可以通过删除客户类的导航属性轻松检查。那么结果就是你所期望的:A表上的 CustomerID 列,B / C上没有 CustomerID 列表。



所以为了解决这个问题,你需要具体告诉EF如何解决循环引用。不确定这是可能的,但是,恐怕您将需要省略客户中的Bs / Cs属性,并编写一个LINQ查询来检索信息。 p>

如果您需要客户类中的属性,您可以这样做:

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

//这是必须访问相关的Bs / Cs
//也不能是私有的,否则EF不会正确地重载
public virtual ICollection< A> ;作为{get;组; }

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


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!

解决方案

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:

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>(); } }
}

这篇关于是否支持导航属性的继承?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆