Access properties of child objects from a base object

More than a year later, from my first question about SO ( Filter base entity from properties of child objects ), I have a similar problem.

I have an abstract base type

public abstract class Base{ } 

I have children that inherit this base type

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

All child objects have a NavigationProperty property. The NavigationProperty class is similar to

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

There is a one-to-one mapping between Child2 and NavigationProperty; One-to-many relationships between Child1 and NavigationProperty. In order for this display to work, I use TPT. My first question is: can I move

  public NavigationProperty NavigationProperty {get; set; } 

to base class?

I have been trying this all day and have had no success. If this is not possible, I can at least access NavigationProperty from the base type. In the end, the guys have this property, I tried something like

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

But the entity infrastructure gives the following error.

  Sequence contains more than one matching element 

I can use something like

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

But I do not want to introduce these additional methods. Are they able to do this more elegantly?

Edit:

I forgot to mention that I already tried to put the [NotMapped] attribute. I assume that the EF [NotMapped] attribute is inherited too, so the child properties are also not displayed.

I do not expect Linq-to-Entites to work. I do not want to be able to query basic objects with navigational properties. I just want to get rid of the GetNavigationProperty and SetNavigationProperty methods. Therefore, when I try to access NavigationProperty from the base class, it must be loaded into memory, that’s all. However, after a week of effort, I do not think this is possible.

+4
source share
3 answers

Can i move around

public NavigationProperty NavigationProperty {get; set; }

to base class?

No, because the inverse properties in the NavigationProperty object are for Child1 and Child2 , not Base . Navigation properties must always be properties of the declared type and cannot be moved to the base type in the inheritance chain.

For the second problem, you can try to exclude the abstract navigation property from the display:

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

(or modelBuilder.Entity<Base>().Ignore(b => b.NavigationProperty); with the Fluent API).

You cannot use Base.NavigationProperty in any queries because you cannot use non-display properties with LINQ-to-Entities.

+1
source

EDIT x1 Updated code to avoid literal strings for property name

A little reflection seems to do the job. Class customization;

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

And in your code;

 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" 

Does this fit your requirements? This is a bit more awkward than using the abstract method, but it at least means you don't need to refactor each child class

+1
source

To find support in the Entity Framework for your scenario, you can try the following:

 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
source

All Articles