i need to add a many to many relationship with UserIdentity in asp net core (i.e: a user can have many books and a book can have many user owners)
I have the book c
Simple, public string ApplicationUserId { get; set; }
ApplicationUser has a default key type of string
.
If you do want to use int, simple do:
public class ApplicationUser : IdentityUser<int>
Be sure to declare this relationship in your DbContext.
Here's a sample:
entityTypeBuilder.HasKey(pcp => new { pcp.CurrencyPairId, pcp.IsMain })
.HasName("PartialCurrencyPair_CK_CurrencyPairId_IsMain");
entityTypeBuilder.HasOne(pcp => pcp.Currency).WithMany(c => c.PartialCurrencyPairs)
.HasForeignKey(pcp => pcp.CurrencyId)
.HasConstraintName("PartialCurrencyPairs_Currency_Constraint");
entityTypeBuilder.HasOne(pcp => pcp.CurrencyPair).WithMany(cp => cp.PartialCurrencyPairs)
.HasForeignKey(pcp => pcp.CurrencyPairId)
.HasConstraintName("PartialCurrencyPairs_CurrencyPair_Constraint");
EDIT
You don't have to explicitly define the generics together with the base class (IdentityUser). You simply do this:
services.AddIdentity<ApplicationUser, Role>()
.AddEntityFrameworkStores<NozomiAuthContext>()
.AddDefaultTokenProviders();
This assumes Role and ApplicationUser share the same key type of string
, where they are overloads of IdentityRole and IdentityUser respectively.
In your UserBook
model class you have used UserId
of type int
for ApplicationUser
but in your ApplicationUser
model class you are inheriting IdentityUser
where primary key Id
is of type string
by default, that means your ApplicationUser
's Id
is of type string
. So there will be a primary key type mismatch for Foreignkey
in UserBook
table.
Solution-1: If you have no problem to keep ApplicationUser
's primary key Id
of type string
, then just change the UserId
type to string in UserBook
model class as follows:
public class UserBook
{
public string UserId { get; set; }
public ApplicationUser ApplicationUser { get; set; }
public int BookId { get; set; }
public Book Book { get; set; }
}
Solution-2: If you want to change ApplicationUser
's primary key Id
from default string
type to int
, then specify the key type as int
while you are inheriting IdentityUser
as follows:
public class ApplicationUser : IdentityUser<int>
{
public ICollection<UserBook> UserBooks { get; set; }
}
Now you have to make changes in ConfigureServices
method of the Startup class as follows:
services.AddDefaultIdentity<IdentityUser<int>>() // here replace `IdentityUser` with `IdentityUser<int>`
.AddDefaultUI()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
Now finally your model configuration (for both Solution-1 and Solution-2) using Fluent Api
should be as follows:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<UserBook>()
.HasKey(ub => new { ub.UserId, ub.BookId });
modelBuilder.Entity<UserBook>()
.HasOne(ub => ub.ApplicationUser)
.WithMany(au => au.UserBooks)
.HasForeignKey(ub => ub.UserId);
modelBuilder.Entity<UserBook>()
.HasOne(ub => ub.Book)
.WithMany() // If you add `public ICollection<UserBook> UserBooks { get; set; }` navigation property to Book model class then replace `.WithMany()` with `.WithMany(b => b.UserBooks)`
.HasForeignKey(ub => ub.BookId);
}