Search code examples
c#.netentity-frameworkcode-first

Entity Framework one-to-zero with different tables


I am wondering if it is possible to make one table related to many.

This is what I got now (working one-to-zero-or-one relation between Report and ReportHeader):

public class Report
{
  public int Id {get; set;}
  public ReportHeader ReportHeader {get; set;}

  [ForeignKey("ReportHeader")]
  public int ReportHeaderId {get; set;}
}

public class ReportHeader
{
  [Key, ForeignKey("Report")]
  public int Id {get; set;}

  public Report Report {get; set;}
}

At this point I want to add table named Style to Report BUT also to table ReportHeader. Thus, the relations would look like this:

Report
|--ReportHeader
|   |-- Style
|
|-- Style

After that the classes should look like:

public class Report
{
  public int Id {get; set;}

  public ReportHeader ReportHeader {get; set;}
  public Style Style {get; set;}

  [ForeignKey("ReportHeader")]
  public int ReportHeaderId {get; set;}

  [ForeignKey("Style")]
  public int StyleId {get; set;}
}

public class ReportHeader
{
  [Key, ForeignKey("Report")]
  public int Id {get; set;}

  [ForeignKey("Style")]
  public int StyleId {get; set;}

  public Report Report {get; set;}
  public Style Style {get; set;}
}

This is so much fun... until it comes to think about the Style class. At this point I have no idea how to design it. Is that even possible to make that class be in two relations with different tables?

public class Style
{
  // ???
  //[Key, ForeignKey("Report"), ForeignKey("ReportHeader")]
  public int Id {get; set;}

  public ReportHeader ReportHeader {get; set;}
  public Report Report {get; set;}
}

Solution

  • At this case you should to mask your desired relation: one-to-one as many-to-one:

    public BaseClass
    {
        //indeed, collection always will have zero or one items
        public virtual ICollection<Style> styles {get; set;}
    
        [NotMapped]
        public Style style {
           get { return styles.FirstOrDefault(); } 
           set { styles.Add(value); };
        }
    }
    
    public class Report : BaseClass
    {
        //other stuff...
    }
    
    public class ReportHeader : BaseClass
    {
        //other stuff...
    }
    
    public class Style
    {
        public int Id {get; set;}
    
        public virtual Report report {get; set;}
        [Index(IsUnique = true)]//to ensure that relation is exactly one-to-one
        public int? reportId {get; set;}
    
        public virtual ReportHeader reportHeader {get; set;}
        [Index(IsUnique = true)]//to ensure that relation is exactly one-to-one
        public int? reportHeaderId {get; set;}
    }