2013-02-25 69 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 */ 
     } 
    } 
} 
相關問題