2013-02-25 73 views
4

从我在SO(Filter base entity from child entities' properties)上的第一个问题开始超过一年后,我遇到了类似的问题。从基地实体访问子实体的属性

我有一个抽象基类

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

Child2和NavigationProperty之间存在一对一映射; Child1和NavigationProperty之间的一对多关系。为了使这些映射工作,我正在使用TPT。我的第一个问题是,我可以移动

public NavigationProperty NavigationProperty {get; set; } 

要基类吗?

我想这一整天,并没有任何成功。如果这是不可能的,我可以至少从基类访问NavigationProperty。在所有孩子都拥有这个属性后,我尝试了类似于

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

但实体框架给出了以下错误。

Sequence contains more than one matching element 

我可以使用类似

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]属性也被继承,所以子属性也没有映射。

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

回答

1

能否将

public NavigationProperty NavigationProperty {get; set; }

基类?

没有,因为在实体NavigationProperty逆属性是指Child1Child2,而不是Base。导航属性始终必须是声明为类型的的属性,并且不能将其移至继承链中的基本类型。

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

public abstract class Base { 
    [NotMapped] 
    public abstract NavigationProperty NavigationProperty {get; set; } 
} 

(或modelBuilder.Entity<Base>().Ignore(b => b.NavigationProperty);用流利的API)。

您将无法在任何查询中使用Base.NavigationProperty,因为您不能在LINQ-to-Entities中使用未映射的属性。

1

编辑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" 

这是否符合您的要求?这比使用abstract方法多一点笨重,但它至少意味着你不必重构每个子类

+0

+1。但是,实体框架不允许在基类上使用“Public NavigationProperty NavigationProperty”。 '[未映射]'属性被继承。如果未使用[未映射],则会给出“序列包含多个匹配元素”错误。所以基本属性名称应该不同。即使采用这种方式,作为字符串传递的属性名称对于我们的项目来说也是不可接受的。当我问这个问题时,我认为这种行为应该是可能的,而不需要任何这些黑客行为。但我想我错了。 – boran 2013-03-08 22:25:22

1

短实体框架中找到适合您的方案的支持,你可以试试这个:

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 */ 
     } 
    } 
} 
相关问题