Search code examples
c#entity-frameworkmany-to-manyef-fluent-api

Entity Framework Many-Too-Many Not Populating Results


I'm trying to map a many-too-many relationship in C# EF with code first migrations.

The issue that I'm having is that no results are being populated from the related table. Take this piece of code for example, _role contains no permissions whereas it should contain 4 results:

foreach (Role _role in _dbContext.Roles) //_dbContext.Roles.Count = 2
{
    foreach(Permission _permission in _role.Permissions) //_role.Permissions.Count = 0
    {
        //Do something with each _permission
    }
}

The classes look like this:

[Table("Roles")]
public partial class Role
{
    public Role()
    {
        Permissions = new HashSet<Permission>();
    }

    [Key]
    public int RoleId { get; set; }

    public string RoleName { get; set; }
    public ICollection<Permission> Permissions { get; set; }
}

[Table("Permissions")]
public partial class Permission
{
    public Permission()
    {
        Roles = new HashSet<Role>();
    }

    [Key]
    public int PermissionId { get; set; }

    public string PermissionName { get; set; }
    public virtual ICollection<Role> Roles { get; set; }
}

And finally the Fluent API:

modelBuilder.Entity<Permission>()
    .HasMany(e => e.Roles)
    .WithMany(e => e.Permissions)
    .Map(m => m
        .ToTable("_Lnk_Role_Permission")
        .MapLeftKey("PermissionId")
        .MapRightKey("RoleId"));

After inspecting the database, the tables, keys and data are all in order and manually adding and querying data produces the correct results. When trying to access the data, roles are present but no permissions.

Can anybody see where it could be going wrong?


Solution

  • Well after hours of head scratching, I missed out Virtual from the ICollection. The modified class looks like so:

    public partial class Role
    {
        public Role()
        {
            Permissions = new HashSet<Permission>();
        }
    
        [Key]
        public int RoleId { get; set; }
    
        public string RoleName { get; set; }
        public Virtual ICollection<Permission> Permissions { get; set; } //Notice the virtual?!
    }