Many to many relation between Identity and custom

2019-04-29 11:46发布

问题:

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. 

回答1:

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; }
}


回答2:

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);


回答3:

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 :)