EF Core:如何让所有生成的迁移包含通用列?
解决方案
问题根源
你之前为抽象基类Entity创建了IEntityTypeConfiguration<Entity>,这会让EF将Entity视为实体类型,即使它是抽象的,仍会生成Entities表存储基类属性;同时TPT架构下子类属性会单独存放在子类表,通过外键关联基类表,导致Key列只在基类表中,不符合需求。
实现方案(VB.NET)
1. 基类与实体类
Public MustInherit Class Entity Public Property Id As Integer Public Property Key As Guid End Class Public Class City Inherits Entity Public Property Name As String ' 修正原代码中Name的类型错误 Public Property Code As String End Class
2. DbContext配置
Imports Microsoft.EntityFrameworkCore Imports System.Linq Public Class AppDbContext Inherits DbContext ' 仅注册具体实体的DbSet,不要添加DbSet(Of Entity) Public Property Cities As DbSet(Of City) Protected Overrides Sub OnConfiguring(optionsBuilder As DbContextOptionsBuilder) optionsBuilder.UseSqlServer("你的数据库连接字符串") End Sub Protected Overrides Sub OnModelCreating(modelBuilder As ModelBuilder) MyBase.OnModelCreating(modelBuilder) ' 遍历所有继承自Entity的具体实体,统一配置Key列的默认值 For Each entityType In modelBuilder.Model.GetEntityTypes() _ .Where(Function(t) t.ClrType.IsSubclassOf(GetType(Entity)) AndAlso Not t.ClrType.IsAbstract) modelBuilder.Entity(entityType.ClrType) _ .Property(Of Guid)("Key") _ .IsRequired() _ .HasDefaultValueSql("NEWID()") Next ' 应用具体实体的表配置 modelBuilder.ApplyConfiguration(New CityConfiguration()) End Sub End Class
3. 实体表配置
Imports Microsoft.EntityFrameworkCore Imports Microsoft.EntityFrameworkCore.Metadata.Builders Public Class CityConfiguration Implements IEntityTypeConfiguration(Of City) Public Sub Configure(builder As EntityTypeBuilder(Of City)) Implements IEntityTypeConfiguration(Of City).Configure ' 指定实体对应的表名 builder.ToTable("Cities") ' 可在此配置当前实体的专属属性规则 builder.Property(Function(c) c.Name).HasMaxLength(100).IsRequired() builder.Property(Function(c) c.Code).HasMaxLength(10).IsRequired() End Sub End Class
实现方案(C#)
1. 基类与实体类
public abstract class Entity { public int Id { get; set; } public Guid Key { get; set; } } public class City : Entity { public string Name { get; set; } public string Code { get; set; } }
2. DbContext配置
using Microsoft.EntityFrameworkCore; using System.Linq; public class AppDbContext : DbContext { public DbSet<City> Cities { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer("你的数据库连接字符串"); } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // 遍历所有继承自Entity的具体实体,统一配置Key列的默认值 foreach (var entityType in modelBuilder.Model.GetEntityTypes() .Where(t => t.ClrType.IsSubclassOf(typeof(Entity)) && !t.ClrType.IsAbstract)) { modelBuilder.Entity(entityType.ClrType) .Property<Guid>("Key") .IsRequired() .HasDefaultValueSql("NEWID()"); } modelBuilder.ApplyConfiguration(new CityConfiguration()); } }
3. 实体表配置
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; public class CityConfiguration : IEntityTypeConfiguration<City> { public void Configure(EntityTypeBuilder<City> builder) { builder.ToTable("Cities"); builder.Property(c => c.Name).HasMaxLength(100).IsRequired(); builder.Property(c => c.Code).HasMaxLength(10).IsRequired(); } }
方案优势
- 不会生成
Entities基类表,所有具体实体都有独立的表 - 统一配置
Key列的默认值,避免重复代码 - 每个实体表会自动包含基类的
Id和Key属性,满足需求
内容的提问来源于stack exchange,提问作者InteXX
相关产品推荐
相关产品推荐

