Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Many to many relation between Identity and custom table. EF7 - Code first

How can I make many to many relation between AspNetRoles from Identity 3.0 and my custom table? I want simple 3 table, with both PermissionId and RoleId, something like AspNetUsersRole. I have something like this:

public class Permission
{
    public int PermissionId { get; set; }
    public string Name { get; set; }
    public virtual ICollection<ApplicationRole> Roles { get; set; }
}

public class ApplicationRole : IdentityRole
{
    public virtual ICollection<Permission> Permissions { get; set; }
}

But when I want to add migration, I got error:

 Unable to determine the relationship represented by navigation property 'ApplicationRole.Permissions' of type 'ICollection<Permission>'. Either manually configure the relationship, or ignore this property from the model. 
like image 756
Fikoblin Avatar asked Jul 18 '16 13:07

Fikoblin


People also ask

What is many-to-many relationships in code first approach?

A many-to-many relationship is defined in code by the inclusion of collection properties in each of the entities - The Categories property in the Book class, and the Books property in the Category class: public class Book. { public int BookId { get; set; }

How do you implement many-to-many relationship in code?

The many-to-may relationship can be achieved using HasMany and WithMany methods. The default conventions for many-to-many relationships creates a joining table with the default naming conventions. You can customize a joining table name and column names using Fluent API.

How do you create a many-to-many relationship in EF core?

Many-to-many relationships require a collection navigation property on both sides. They will be discovered by convention like other types of relationships. The way this relationship is implemented in the database is by a join table that contains foreign keys to both Post and Tag .


Video Answer


3 Answers

EF Core (EF7) does not currently support many to many relationship without a join entity. (Reference)

So, what you should do is to create an entity class for the join table and mapping two separate one-to-many relationships. Like;

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<PostTag>()
        .HasKey(t => new { t.PostId, t.TagId });

    modelBuilder.Entity<PostTag>()
        .HasOne(pt => pt.Post)
        .WithMany(p => p.PostTags)
        .HasForeignKey(pt => pt.PostId);

    modelBuilder.Entity<PostTag>()
        .HasOne(pt => pt.Tag)
        .WithMany(t => t.PostTags)
        .HasForeignKey(pt => pt.TagId);
}

public class PostTag
{
        public int PostId { get; set; }
        public Post Post { get; set; }

        public string TagId { get; set; }
        public Tag Tag { get; set; }
}
like image 182
Emre Bolat Avatar answered Nov 15 '22 05:11

Emre Bolat


Regarding to this question answer, it can be done more easily like this-

class Photo
{
    public int Id { get; set; }
    public ICollection<PersonPhoto> PersonPhotos{ get; set; }
}

class PersonPhoto
{
    public int PhotoId { get; set; }
    public Photo Photo { get; set; }

    public int PersonId { get; set; }
    public Person Person { get; set; }
}

class Person
{
    public int Id { get; set; }
    public ICollection<PersonPhoto> PersonPhotos{ get; set; }
}

Be sure to configure PersonPhoto with a composite key:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<PersonPhoto>().HasKey(x => new { x.PhotoId, x.PersonId });
}

To navigate, use a Select:

// person.Photos
var photos = person.PersonPhotos.Select(c => c.Photo);
like image 40
Abrar Jahin Avatar answered Nov 15 '22 07:11

Abrar Jahin


Add This namespace-

using Microsoft.AspNetCore.Identity;


public class Permission
{
     [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
     public int PermissionId { get; set; }
     public string Name { get; set; }
     public string UserIdFK { get; set; } //Foreign Key of Identity tbl

     [ForeignKey("UserIdFK")]
     public IdentityUser UserDetail { get; set; }
}

That's it, Happy coding :)

like image 25
panky sharma Avatar answered Nov 15 '22 07:11

panky sharma