I am experiencing an error with AspNetCore.Identity.EntityFrameworkCore 2.1.6 using code-first database migrations. The error is
The entity type 'ModeratedUser' requires a primary key to be defined.
This is confusing me as I have a primary key defined for all entities using Fluent Api. I have done research on this specific issue and all posts I have ran across are referring to different issues (Please note that I have followed the following for defining my many-to-many relationship: https://www.learnentityframeworkcore.com/configuration/many-to-many-relationship-configuration)
Here are the entities and the entity type configurations:
public class ModeratedUser { public Guid ModeratedId { get; set; } public virtual List<ModeratorModerated> ModeratorModerated { get; set; } } public class ModeratorUser { public Guid ModeratorId { get; set; } public virtual List<ModeratorModerated> ModeratorModerated { get; set; } } //explicit class to outline many to many between moderated and moderators public class ModeratorModerated { public Guid ModeratorId { get; set; } public Guid ModeratedId { get; set; } public ModeratedUser Moderated { get; set; } public ModeratorUser Moderator { get; set; } } Here is the entity type configurations:
public abstract class ModeratedConfiguration : EntityMappingConfiguration<ModeratedUser> { public override void MapToConfig(EntityTypeBuilder<ModeratedUser> builder) { builder.HasKey(x => x.ModeratedId); builder.ToTable("ModeratedUsers", "Mod"); } } public abstract class ModeratorsConfiguration : EntityMappingConfiguration<ModeratorUser> { public override void MapToConfig(EntityTypeBuilder<ModeratorUser> builder) { builder.HasKey(x => x.ModeratorId); builder.ToTable("ModeratorUsers", "Mod"); } } public abstract class ModeratorModeratedConfiguration : EntityMappingConfiguration<ModeratorModerated> { public override void MapToConfig(EntityTypeBuilder<ModeratorModerated> builder) { builder.HasKey(x => new { x.ModeratedId, x.ModeratorId }); builder.HasOne(x => x.Moderated) .WithMany(x => x.ModeratorModerated) .HasForeignKey(x => x.ModeratedId); builder.HasOne(x => x.Moderator) .WithMany(x => x.ModeratorModerated) .HasForeignKey(x => x.ModeratorId); builder.ToTable("ModeratorModerated", "Mod"); } } As you can see, I have set the .HasKey for both the ModeratorUser.cs and ModeratedUser.cs and have set the CompositeKey for the ModeratorModerated.cs configuration class.
Here's my Context class:
public class DbContext : IdentityDbContext<ApplicationUser> { public DbContext(DbContextOptions<DbContext> options) : base(options) { } public DbSet<CatalogItem> CatalogItems { get; set; } public DbSet<ModeratedUser> ModeratedUsers { get; set; } public DbSet<ModeratorUser> ModeratorUsers { get; set; } protected override void OnModelCreating(ModelBuilder builder) { builder.HasDefaultSchema("UDC"); builder.AddEntityConfigurationsFromAssembly(GetType().Assembly); base.OnModelCreating(builder); } } And here is my ModelBuilderExtensions.cs class that I use to instantiate the EntityMappingConfigurations...
public interface IEntityMappingConfiguration { void MapToConfig(ModelBuilder b); } public interface IEntityMappingConfiguration<T> : IEntityMappingConfiguration where T : class { void MapToConfig(EntityTypeBuilder<T> builder); } public abstract class EntityMappingConfiguration<T> : IEntityMappingConfiguration<T> where T : class { public abstract void MapToConfig(EntityTypeBuilder<T> b); public void MapToConfig(ModelBuilder b) { MapToConfig(b.Entity<T>()); } } public static class ModelBuilderExtenions { private static IEnumerable<Type> GetMappingTypes(this Assembly assembly, Type mappingInterface) { return assembly.GetTypes().Where(x => !x.IsAbstract && x.GetInterfaces().Any(y => y.GetTypeInfo().IsGenericType && y.GetGenericTypeDefinition() == mappingInterface)); } public static void AddEntityConfigurationsFromAssembly(this ModelBuilder modelBuilder, Assembly assembly) { var mappingTypes = assembly.GetMappingTypes(typeof(IEntityMappingConfiguration<>)); foreach (var config in mappingTypes.Select(Activator.CreateInstance).Cast<IEntityMappingConfiguration>()) { config.MapToConfig(modelBuilder); } } } The error coming from the PackageManagerConsole window in VS2017 is:
System.InvalidOperationException: The entity type 'ModeratedUser' requires a primary key to be defined.
As you can see, small app but I can't get past my first m-m using EFCore. This wasn't nearly as challenging in EF6.2. What am I missing here?