C# 访问子实体';来自基本实体的属性

C# 访问子实体';来自基本实体的属性,c#,entity-framework,C#,Entity Framework,在我提出关于SO()的第一个问题一年多之后,我遇到了一个类似的问题 我有一个抽象的基类型 public abstract class Base{ } 我有一些从这个基类型继承的子实体 public class Child1 : Base{ public virtual NavigationProperty NavigationProperty {get; set; } public int NavigationPropertyId {get; set} } public cl

在我提出关于SO()的第一个问题一年多之后,我遇到了一个类似的问题

我有一个抽象的基类型

public abstract class Base{
}
我有一些从这个基类型继承的子实体

public class Child1 : Base{
    public virtual NavigationProperty NavigationProperty {get; set; }
    public int NavigationPropertyId {get; set}
}

public class Child2 : Base{
    public virtual NavigationProperty NavigationProperty {get; set; }
}
子实体都具有NavigationProperty属性。NavigationProperty类如下所示

 public class NavigationProperty{
    public virtual ICollection<Child1> Child1s {get; set;}
    public virtual Child2 Child2s {get; set;}
 }
到基类

我试了一整天,没有成功。如果不可能,我至少可以从基类型访问NavigationProperty。在所有的孩子都拥有这一财产之后,我尝试了类似的方法

 public abstract class Base{
      public abstract NavigationProperty NavigationProperty {get; set; }
 }
 ....
 public abstract class Child2{
      public override NavigationProperty NavigationProperty {get; set; }
 }
   public abstract class Base{
      public abstract NavigationProperty GetNavigationProperty();
   }

  public abstract class Child2{
      public override NavigationProperty NavigationProperty {get; set; }
      public override NavigationProperty GetNavigationProperty(){
           return NavigationProperty;
      }
 }
但实体框架给出了以下错误

 Sequence contains more than one matching element 
我可以用

 public abstract class Base{
      public abstract NavigationProperty NavigationProperty {get; set; }
 }
 ....
 public abstract class Child2{
      public override NavigationProperty NavigationProperty {get; set; }
 }
   public abstract class Base{
      public abstract NavigationProperty GetNavigationProperty();
   }

  public abstract class Child2{
      public override NavigationProperty NavigationProperty {get; set; }
      public override NavigationProperty GetNavigationProperty(){
           return NavigationProperty;
      }
 }
但我不想介绍这些额外的方法。他们有没有办法更优雅地实现这一点

编辑:

我忘了提到我已经试过把
[NotMapped]
属性放进去了。我猜EF
[NotMapped]
属性也会被继承,因此子属性也不会被映射

我不想让所有人都去工作。我不希望能够查询具有导航属性的基本实体。我只是想摆脱GetNavigationProperty和SetNavigationProperty方法。所以,当我尝试从基类访问NavigationProperty时,它应该加载到内存中,仅此而已。然而,经过一周的努力,我认为这是不可能的

我能搬家吗

公共导航属性导航属性{get;set;}

到基类

否,因为实体
NavigationProperty
中的反向属性指的是
Child1
Child2
,而不是
Base
。导航属性始终必须是声明类型的属性,并且不能移动到继承链中的基类型

对于第二个问题,您可以尝试从映射中排除抽象导航属性:

public abstract class Base {
    [NotMapped]
    public abstract NavigationProperty NavigationProperty {get; set; }
}
(或
modelBuilder.Entity().Ignore(b=>b.NavigationProperty);
使用Fluent API)


您将无法在任何查询中使用
Base.NavigationProperty
,因为您不能将未映射属性与LINQ一起使用到实体。

编辑x1更新的代码以避免属性名称的文字字符串

稍微思考一下似乎就行了。班级设置

public class NavigationProperty
{
    public NavigationProperty(string name)
    {
        Name = name;
    }

    public string Name { get; set; }
}

public abstract class Base
{
    public NavigationProperty NavigationProperty
    {
        get
        {
            string propertyName = MethodBase.GetCurrentMethod().Name.Replace("get_", string.Empty);
            PropertyInfo property = this.GetType().GetProperty(propertyName);
            if (property != null)
            {
                nav = (NavigationProperty)property.GetValue(this, new object[] { });
            }

            return nav;
        }
        set
        {
            string propertyName = MethodBase.GetCurrentMethod().Name.Replace("set_", string.Empty);
            PropertyInfo property = this.GetType().GetProperty(propertyName);
            if (property != null)
            {
                property.SetValue(this, value, new object[] { });
            }
        }
    }
}

public class Child1 : Base {
    public NavigationProperty NavigationProperty { get; set; }
    public int NavigationPropertyId { get; set; }
}

public class Child2 : Base{
    public NavigationProperty NavigationProperty { get; set; }
}
在你的代码中

Child1 c1 = new Child1() { NavigationProperty = new NavigationProperty("child1Value") };
Child2 c2 = new Child2() { NavigationProperty = new NavigationProperty("child2Value") };
Base somebase = c1;
NavigationProperty childNav = somebase.NavigationProperty;
// childNav.Name now contains "child1Value"

这符合你的要求吗?与使用
抽象方法相比,它有点笨重,但它至少意味着您不必重构每个子类除非在实体框架中为您的场景找到支持,否则您可以尝试以下方法:

public interface IHasNavigationProperty {
    NavigationProperty NavigationProperty { get; }
}

public class Child1 : Base, IHasNavigationProperty {
    public NavigationProperty NavigationProperty { get; set; }
}

public class Base {
    public void AMethodThatDoesStuff() {
        if (this is IHasNavigationProperty) {
            var navigationProperty = ((IHasNavigationProperty)this).NavigationProperty;

            /* do stuff with NavigationProperty */
        }
    }
}

+1.谢谢你的努力。但是,实体框架不允许对基类使用
公共导航属性NavigationProperty
<代码>[未映射]
属性被继承。如果未使用[not mapped],则会给出序列包含多个匹配元素的
错误。因此,基本属性名称应该不同。即使采用这种方式,作为字符串传递的属性名称对于我们的项目来说也是不可接受的。当我问这个问题时,我认为这种行为应该是可能的,而不需要任何这些黑客。但我想我错了。