Search code examples
asp.net-mvcentity-frameworkapifluent

Entity Framework relate second table


How can I relate the tables below by fluent api?

I need to get the second table data via LinkTable which stores ids of Main and Second tables.

enter image description here

Here are my models:

public class MainTable
{
        public int ID { get; set; }
        ...
        ...
        public ICollection<LinkTable> LinkTable { get; set; }
}

public class LinkTable
{
        public int ID { get; set; }
        ...
        ...
        public MainTable MainTable  { get; set; }
        public SecondTable SecondTable { get; set; }
}

public class SecondTable
{
        public int ID { get; set; }
        ...
        ...
        public ICollection<LinkTable> LinkTable { get; set; }
}

I mapped like this:

HasRequired(t => t.MainTable).WithMany(t => t.LinkTable).HasForeignKey(t => t.MainTable_ID);
HasRequired(t => t.SecondTable).WithMany(t => t.LinkTable).HasForeignKey(t => t.SecondTable_ID);

And trying to get data :

MyDBContext.MainTable.Include("LinkTable").FirstOrDefault();

When I was trying foreach the LinkTable to get SecondTable data I got an error:

Object reference not set...

 @foreach (var item in Model.LinkTable)
 {
     <p>@item.SecondTable.ID</p>
 }

Solution

  • To avoid that exception, you need to initialize your navigation property in a constructor:

    public class MainTable
    {
    
        public MainTable()
        {
          LinkTable=new List<LinkTable>();
        }
        public int ID { get; set; }
        ...
        ...
        public ICollection<LinkTable> LinkTable { get; set; }
    }
    

    Also, you could use Include extension method which is strongly typed and could avoid you possible run-time exceptions:

    MyDBContext.MainTable.Include(mt=>mt.LinkTable).FirstOrDefault();
    

    Now if you want to load another level, in this case SecondTable, you can do this:

    MyDBContext.MainTable.Include(mt=>mt.LinkTable.Select(lt=>lt.SecontTable)).FirstOrDefault();
    

    In the link I quoted above you can find more examples about how to load different levels.