Kinexus
Kinexus

Reputation: 12904

EF 6 Many To Many Navigation Property null

I have defined a Many to Many relationship between 2 objects. Each object exposes the same Navigation property in order for me to traverse the relationships by code. The setup is as follows;

    public class Message : Entity<int>
    {
        public int UserId { get; set; }

        public User User { get; set; }

        public Guid Reference { get; set; } = Guid.NewGuid();

        public virtual ICollection<MessageGroup> MessageGroups { get; set; } = new HashSet<MessageGroup>();
    }
}

  public class Group : Entity<int>
    {
        public int UserId { get; set; }

        public User User { get; set; }

        public Guid Reference { get; set; } = Guid.NewGuid();

        public virtual ICollection<MessageGroup> MessageGroups { get; set; } = new HashSet<MessageGroup>();

    }

 public class MessageGroup
    {
        public int MessageId { get; set; }

        public Message Message { get; set; }

        public int GroupId { get; set; }

        public Group Group { get; set; }
    }

and this in my Context;

   protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {

                modelBuilder.Entity<MessageGroup>()
                       .HasKey(bc => new { bc.GroupId, bc.MessageId });

                modelBuilder.Entity<MessageGroup>()
                    .HasRequired(bc => bc.Group)
                    .WithMany(b => b.MessageGroups)
                    .HasForeignKey(bc => bc.GroupId)
                    .WillCascadeOnDelete(false);

                modelBuilder.Entity<MessageGroup>()
                    .HasRequired(bc => bc.Message)
                    .WithMany(c => c.MessageGroups)
                    .HasForeignKey(bc => bc.MessageId)
                    .WillCascadeOnDelete(false);

}

However, when I attempt to load a Message that has multiple groups (records are correct in MessageGroup table), only the Messages are shown. For Information, I am loading these through the Messages DbSet. When I then load the Group through the Groups DbSet, the reverse happens, and only the Groups are shown.

Loaded from Messages DbSet;

enter image description here

Loaded from Group DbSet;

enter image description here

I can get both by using the MessageGroup DbSet and Including them;

var messageGroups = context.MessageGroups.Where(x => x.MessageId == id).Include(x => x.Group).Include(x => x.Message).ToList();

but I want to be able to load my Message or Group and have these available.

For information, my context is wrapped around another layer and I have exposed a few methods for each Type but ultimately, I am calling;

   public T Get(U id)
        {
            return _dbSet.Find(id);
        }

Upvotes: 1

Views: 477

Answers (1)

Ivan Stoev
Ivan Stoev

Reputation: 205849

When a collection navigation property is loaded, the EF navigation property fixup also loads the corresponding inverse navigation property. But other navigation properties must be loaded explicitly (eager, explicit or lazy).

Since you seem to rely on lazy loading the MessageGroups collection navigation properties, you should make the inverse reference navigation properties in MessageGroup virtual too:

public class MessageGroup
{
    public int MessageId { get; set; }

    public virtual Message Message { get; set; }

    public int GroupId { get; set; }

    public virtual Group Group { get; set; }
}

Upvotes: 2

Related Questions