I have a Notification class
public class Notification
{
public int NotificationId { get; set; }
public string NotificationMessage { get; set; }
public DateTime NotificationSentOn { get; set; }
//TODO: not sure how to map this in fluent api
// a Notification can go to many users
public ICollection<ApplicationUser> ReceivingUsers { get; set; }
}
and the extension of ApplicationUser
public class ApplicationUser : IdentityUser
{
public ApplicationUser()
{
IsAuthor = false;
}
public string Firstname { get; set; }
public string Lastname { get; set; }
public Gender Gender { get; set; }
public DateTime? DateOfBirth { get; set; }
public DateTime RegisteredDate { get; set; }
public bool IsAuthor { get; set; }
// foreign key to UserProfile using the string ID from ApplicationUser
public UserProfile MemberProfile { get; set; }
// collection of notifications for this user
public ICollection<Notification> Notifications { get; set; }
}
Here is the error relating to the Notifications property in the ApplicationUser class
Unable to determine the relationship represented by navigation property 'ApplicationUser.Notifications' of type 'ICollection'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
I believe the relationship should be one-many , i.e. one Notification goes to many ApplicationUsers, but my normal pattern in Entity Configuration doesn't work, I must be missing something in one of the classes.
I am not sure how to map both the Notifications collection or the foreignkey relation to UserProfile using the fluent API ( I am using EntityConfiguration classes using IEntityTypeConfiguration interface)
Update Per Camilo's answer, I updated my Entity Configurations to include the NavigationUser table setting the primary key as follows
public class NotificationUserEntityConfiguration : IEntityTypeConfiguration<NotificationUser>
{
public void Configure(EntityTypeBuilder<NotificationUser> builder)
{
builder.HasKey(u => new { u.ApplicationUserId, u.NotificationId })
.HasName("PK_NotificationUser");
builder.Property(u => u.NotificationId)
.ValueGeneratedNever()
.IsRequired();
builder.Property(u => u.ApplicationUserId)
.ValueGeneratedNever()
.IsRequired();
}
}
This returned the following from the db creation script
It created a ForeignKey in the ApplicationUser table
table.ForeignKey( name: "FK_AspNetUsers_Notifications_NotificationId",
column: x => x.NotificationId,
principalSchema: "MachineryCtx",
principalTable: "Notifications",
principalColumn: "NotificationId",
onDelete: ReferentialAction.Restrict);
and a ForeignKey in the NotificationUsers table back to notifications
table.ForeignKey( name: "FK_NotificationUser_Notifications_NotificationId",
column: x => x.NotificationId,
principalSchema: "MachineryCtx",
principalTable: "Notifications",
principalColumn: "NotificationId",
onDelete: ReferentialAction.Cascade);
You are trying to model a many-to-many relationship as if it were a one-to-many.
You should have something like this instead:
public class ApplicationUser
{
...
public ICollection<NotificationUser> Notifications { get; set; }
}
public class Notification
{
...
public ICollection<NotificationUser> Users { get; set; }
}
public class NotificationUser
{
public int ApplicationUserId { get; set; }
public int NotificationId { get; set; }
public ApplicationUser User { get; set; }
public Notification Notification { get; set; }
}
That says:
You can either have an IDENTITY
Primary Key or a Composite Primary Key with ApplicationUserId,NotificationId