EF Core 5中如何为两个结构相同的SQL表共用同一个模型类
问题原因
EF Core 默认会将CLR实体类的类名作为映射的数据库表名,你用同一个TableRecord类绑定两个DbSet时,EF Core 无法自动识别两个不同的表映射关系,最终生成的SQL会指向不存在的TableRecord表,因此抛出Invalid object name 'TableRecord'错误。
解决方案
有两种常用方案可以实现同结构表共用同一个实体类,无需重复写属性代码:
方案1:继承空子类实现(最简单,推荐)
你只需要定义两个继承自TableRecord的空类即可,不需要重复编写属性代码,EF Core 会自动按照子类名/DbSet属性名匹配对应的表:
// 原有实体类不变 public class TableRecord { public int Id { get; set; } public DateTime Date { get; set; } public string Title { get; set; } } // 新增两个空的子类 public class Table1 : TableRecord {} public class Table2 : TableRecord {} // 修改DbContext中的DbSet定义 public class MyContext : DbContext { // 其他原有代码不变 public virtual DbSet<Table1> Table1 { get; set; } public virtual DbSet<Table2> Table2 { get; set; } }
注意:EF Core默认会对继承类启用TPH继承策略,自动加Discriminator查询条件,你可以在
OnModelCreating中添加以下配置关闭该行为,完全匹配现有表结构:protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Table1>().HasBaseType((Type)null); modelBuilder.Entity<Table2>().HasBaseType((Type)null); }
修改后原有查询代码不需要改动,直接使用context.Table1、context.Table2即可正常操作。
方案2:共享类型实体配置(无需新增类)
如果你不想新增任何类,可以在OnModelCreating中配置共享类型实体,为同一个TableRecord类绑定两个不同的表映射:
第一步:重写OnModelCreating方法
public class MyContext : DbContext { // 其他原有代码不变 protected override void OnModelCreating(ModelBuilder modelBuilder) { // 配置Table1的映射 modelBuilder.SharedTypeEntity<TableRecord>("Table1", tb => { tb.ToTable("Table1"); tb.HasKey(x => x.Id); tb.Property(x => x.Title).HasMaxLength(100); // 其余字段配置按需添加即可 }); // 配置Table2的映射 modelBuilder.SharedTypeEntity<TableRecord>("Table2", tb => { tb.ToTable("Table2"); tb.HasKey(x => x.Id); tb.Property(x => x.Title).HasMaxLength(100); }); } }
第二步:调整查询写法
查询时需要通过Set<T>(string name)方法指定要操作的实体名:
// 查询Table1的数据 var results = context.Set<TableRecord>("Table1").Where(x => x.Title.Contains("asd")).ToList(); // 查询Table2的数据 var results2 = context.Set<TableRecord>("Table2").Where(x => x.Title.Contains("asd")).ToList();
内容的提问来源于stack exchange,提问作者Tessaract
相关产品推荐
相关产品推荐

