Search code examples
c#entity-frameworkcode-first

EF, How to conditionally include a navigation property that type of it related to value of another property?


I have the bellow entities:

public class Notification
{
    public int Id { get; set; }
    public string Title { get; set; }
    public Guid RefId { get; set; }
    public Object Ref { get; set; } //  << The navigation property: Sometime its type is Poll and sometime is Test, maybe I add other types too 
    public NotifTypes Type { get; set; }
}

public enum NotifTypes
{
    Poll=1,
    Test=2,
    // Other NotifTypes here
}

//-------------------------------------------------------------------

public class Test
{
    public int Id { get; set; }
    public string Title { get; set; }

    public IEnumerable<Notification> { get; set; }
}

public class Poll
{
    public int Id { get; set; }
    public string Answer1 { get; set; }
    public string Answer2 { get; set; }

    public IEnumerable<Notification> { get; set; }
}

OK,

  • When the Type property of Notification object is equal Poll, the RefId will fill by a PollId
  • When type is equal Test, the refId will fill by a TestId.

Now I want conditionally include the related Poll or Test in Ref property. How should I implement it?

I want prevent to add separate Ids like PollId, TestId and.... to Notification because I'm sure that each time just one of them has value, so I want have one RefId and one Ref property instead of them.


Solution

  • I don't know EntityFramework, but you asked me to answer this.

    You're basically reinventing which is not a good relational design. You can read a few of my past answers about this concept:

    I tend to answer MySQL questions, but the answer is the same for any other brand of RDBMS. The fact that you cannot declare an actual foreign key constraint that references multiple tables should be a clue that this design is not right.

    The easiest solution from a data modeling perspective is to create an independent attribute for each of your potential table references. All but one of these will be NULL on a given row.

    I have no idea how EntityFramework might support this. @AluanHaddad's advice sounds good.

    Try not to break relational concepts. Down that path is the Inner-Platform Effect antipattern.