c# - 实体类型 'ModeratedUser'需要定义主键

标签 c# asp.net-core entity-framework-core database-migration

我在使用代码优先数据库迁移时遇到 AspNetCore.Identity.EntityFrameworkCore 2.1.6 错误。错误是

The entity type 'ModeratedUser' requires a primary key to be defined.

这让我很困惑,因为我使用 Fluent Api 为所有实体定义了主键。我已经对这个特定问题进行了研究,我遇到的所有帖子都提到了不同的问题(请注意,我遵循以下内容来定义我的多对多关系:https://www.learnentityframeworkcore.com/configuration/many-to-many-relationship-configuration)

以下是实体和实体类型配置:

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

这是实体类型配置:

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

如您所见,我已为 ModeratorUser.cs 和 ModeeratedUser.cs 设置了 .HasKey,并为 ModeratorModelated.cs 配置类设置了 CompositeKey。

这是我的 Context 类:

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

这是我用来实例化 EntityMappingConfigurations 的 ModelBuilderExtensions.cs 类...

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

来自 VS2017 中 PackageManagerConsole 窗口的错误是:

System.InvalidOperationException: The entity type 'ModeratedUser' requires a primary key to be defined.

如您所见,应用程序很小,但我无法通过使用 EFCore 的第一个 m-m。这在 EF6.2 中几乎没有那么具有挑战性。我在这里缺少什么?

最佳答案

尝试这个改变

public class ModeratedConfiguration : IEntityTypeConfiguration<ModeratedUser>
{
    public void Configure(EntityTypeBuilder<ModeratedUser> builder)
    {
        builder.ToTable("ModeratedUsers", "Mod");
        builder.HasKey(x => x.ModeratedId);
    }
}

public class ModeratorsConfiguration : IEntityTypeConfiguration<ModeratorUser>
{
    public void Configure(EntityTypeBuilder<ModeratorUser> builder)
    {
        builder.ToTable("ModeratorUsers", "Mod");
        builder.HasKey(x => x.ModeratorId);
    }
}

public class ModeratorModeratedConfiguration : IEntityTypeConfiguration<ModeratorModerated>
{
    public void Configure(EntityTypeBuilder<ModeratorModerated> builder)
    {
        builder.ToTable("ModeratorModerated", "Mod");
        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);

    }
}

您的 DbContext 应该是

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.ApplyConfiguration<ModeratedUser>(new ModeratedUser());
        builder.ApplyConfiguration<ModeratedUser>(new ModeratorsConfiguration());
        builder.ApplyConfiguration<ModeratorModerated>(new ModeratorModeratedConfiguration());
        base.OnModelCreating(builder);
    }
}

关于c# - 实体类型 'ModeratedUser'需要定义主键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55821333/

相关文章:

c# - 用于 web-api 触发重定向的 Asp.net 核心授权

c# - 如何更改.Net core中的访问拒绝路由

c# - EF 核心实体数据访问中的强制转换无效

c# - 样板代码替换——这段代码有什么不好的地方吗?

c# - 比较两个 IQueryable 实例

c# - 如果Binding为NULL,则Datagrid中的WPF ComboBox会引发错误

entity-framework-core - 与 EF core 中的 DateTime 相比,生成的日期字符串为 6 位小数(以毫秒为单位)

c# - 在 C# 中,类名介于 "Less than"和 "Greater than"符号之间的目的是什么?

c# - 无法将生产服务器设置为生产

asp.net - 如何在 Entity Framework Core 2.1 中播种枚举