如何将基本实体字段映射到每个子类的不同列

How can I map a base entity field to different columns for each subclass

我有一个基本实体 class,我希望能够继承它,这样我只需为许多不同的特定于实体的存储库编写 1 GetById 方法。但是,由于遗留原因,我的某些数据库表中的 "Id" 列必须称为 "Code"。

我试过(简化版):

public class EntityBase{
    int Id;
}

public class IdEntity : EntityBase{
}

public class CodeEntity : EntityBase{
}

然后在 DbContext 中:

modelBuilder.Entity<IdEntity>(entity =>
{
    entity.HasKey(e=>e.Id).HasName("PK_IdEntity");
    entity.Property(e=>e.Id).HasColumnName("ID");
}

modelBuilder.Entity<CodeEntity>(entity =>
{
    entity.HasKey(e=>e.Id).HasName("PK_CodeEntity");
    entity.Property(e=>e.Id).HasColumnName("Code"); //this seems to be where it breaks
}

这个构建很好,但是当我尝试 运行 它时,我得到一个 InvalidOperationException: 无法在实体类型 'CodeEntity' 上为 属性 'Id' 调用 属性,因为它被配置为导航 属性。 属性 只能用于配置标量属性。

我想做的事情是不可能的吗?这对我来说似乎不太可能,但是正确的方法是什么?

编辑:

事实证明,我实际尝试做的事情比我在此处发布的 "simplified" 代码复杂得多。我想这样做,这样我就可以拥有一个字符串或整数 ID,并使用相同的 GetById 方法。所以我创建了一个 class,它对字符串和 int 都进行了隐式转换,我认为这对 Entity Framework.

是可以的

不是。

运行time 错误是由于试图告诉 EF EntityID 类型的 属性 应该是我的密钥而引起的,而您不允许这样做。

我在 Microsoft 找不到关于 Entity Framework 中键值要求的任何文档,但我发现了另一个 SO 问题,它说键只允许标量和字节 []:Type safe keys with Entity Framework model

我无法得到上面的代码来编译或给出异常,因为你在尝试修复它后已经足够了。虽然我将描述如何编写您想要实现的场景。

如果你想在EF中使用EntityBase.Id作为PK 属性,你需要将其设为public 属性。在您的代码中,它是一个私有字段(因为没有 get/set 方法)。所以你的 EntityBase class 应该是这样的

public class EntityBase
{
    public int Id { get; set; }
}

通过上述更改和 OnModelCreating 代码来映射有问题的实体类型,模型构建工作正常,创建具有所需 table 结构和名称的 tables。

以下是在 dbset 上实现通用 GetById 的小方法。它可以成为通用存储库甚至扩展方法的一部分。

public static T GetById<T>(DbSet<T> dbset, int id)
    where T : EntityBase
{
    return dbset.FirstOrDefault(e => e.Id == id);
}

// example
var entity = GetById(db.Set<IdEntity>(), 2);