Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework User Roles Many to Many Relationship

Hi I'm trying to set up my entity framework for a many to many relationship between User and Role.

The picture below shows what's in the database:

Many to Many relationships

The Model for User is:

public class User : IEntity
    {
        public virtual int UserId { get; set; }
        [Column(TypeName = "varchar")]
        [StringLength(100)]
        public virtual string UserName { get; set; }
        [Column(TypeName = "varchar")]
        [StringLength(100)]
        public virtual string FirstName { get; set; }
        [Column(TypeName = "varchar")]
        [StringLength(100)]
        public virtual string LastName { get; set; }
        [Column(TypeName = "varchar")]
        [StringLength(200)]
        public virtual string EmailAddress { get; set; }
        public int AreaId { get; set; }
        [Column(TypeName = "varchar")]
        [StringLength(64)]
        public string CreatedByUserName { get; set; }
        public DateTime CreatedDateTime { get; set; }
        [Column(TypeName = "varchar")]
        [StringLength(64)]
        public string LastModifiedByUserName { get; set; }
        public DateTime? LastModifiedDateTime { get; set; }

        //Navigation properties
        //public virtual Role Role { get; set; }
        public virtual Area Area { get; set; }

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

}

Model for Role is:

public class Role : IEntity
    {
        public int RoleId { get; set; }
        [Column(TypeName = "varchar")]
        [StringLength(100)]
        public string Name { get; set; }
        [Column(TypeName = "varchar")]
        [StringLength(1000)]
        public string Description { get; set; }
        [Column(TypeName = "varchar")]
        [StringLength(64)]
        public string CreatedByUserName { get; set; }
        public DateTime CreatedDateTime { get; set; }
        [Column(TypeName = "varchar")]
        [StringLength(64)]
        public string LastModifiedByUserName { get; set; }
        public DateTime? LastModifiedDateTime { get; set; }

        //Navigation Properties
        public ICollection<User> Users { get; set; }
    }

UserRole is:

public class UserRole
    {
        public int UserId { get; set; }
        public int RoleId { get; set; }

        //Navigation properties
        public virtual User User { get; set; }
        public virtual Role Role { get; set; }
    }

So I thought I had this set up fine but in my code I go something like:

var roles = from r in user.Roles
                        select r.Name;

and it shoots itself giving errors of:

Server Error in '/' Application.
Invalid object name 'dbo.RoleUser'. 

so I added the following to the context:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<User>()
                .HasMany(i => i.Roles)
                .WithMany(u => u.Users);

}

However now I'm getting errors of:

Server Error in '/' Application. Invalid column name 'Role_RoleId'. Invalid column name 'User_UserId'.

So surely I don't have something set up here correctly. Can andybody point me in the right direction?

like image 362
AnonyMouse Avatar asked Nov 08 '11 01:11

AnonyMouse


1 Answers

You don't need to model the link table UserRole as a class since it has only the primary keys of the tables participate in the relationship. So remove the UserRole class.

If you are modeling an existing database, EF may infer the link table name to be RoleUser. To avoid this you can configure the link table as follows.

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
 {
        modelBuilder.Entity<User>()
            .HasMany(i => i.Roles)
            .WithMany(u => u.Users)
            .Map(m =>
            {
                m.ToTable("UserRole");
                m.MapLeftKey("UserId");
                m.MapRightKey("RoleId");
            });

 }
like image 95
Eranga Avatar answered Sep 18 '22 05:09

Eranga