首页 > 解决方案 > 使用通用类进行继承和成员(代码优先)

问题描述

我很难让 EF 代码优先从以下实体生成数据库:

public class Person : Animal
{
    public int Id { get; set; }
    public Animal Pet { get; set; }
}

public class Animal
{
    public string Name { get; set; }
}

所以从概念上讲,一个人是有名字的动物,他们有一只宠物,也是有名字的动物。我的上下文包含一组人,但包含动物,这就是 Animal 不包含键的原因:

public DbSet<Person> People { get; set; }

如果我尝试使用代码优先创建数据库,则会收到以下错误:

System.Data.Entity.ModelConfiguration.ModelValidationException: One or more validation errors were detected during model generation:

MyProject.Database.Animal: : EntityType 'Animal' has no key defined. Define the key for this EntityType.
Animals: EntityType: EntitySet 'Animals' is based on type 'Animal' that has no keys defined.

如果我删除该Pet字段,我会得到一个带有IdName字段的表格,这是我的预期行为。同样,如果我删除Animal继承,我会得到一个带有IdPet_Name字段的表,这也是我的预期行为。我想要得到的是一个带有Id,NamePet_Name字段的表。

不禁觉得我在这里遗漏了一些非常基本的东西,因为我已经在其他 ORM 上做到了这一点而没有问题。谁能告诉我如何使用 EF 6.2 做到这一点?

标签: entity-framework

解决方案


对于将来阅读此内容的任何其他人,EF 将类视为实体或复杂类型。实体拥有自己的表,而复杂类型拥有自己的字段,作为字段添加到包含它们作为属性的父类中。如果您将一个类实例声明为另一个类的属性,那么 EF 会立即假定它是一个实体;如果它看到你试图将它用作继承层次结构中的基类,那么它会假定它是一个复杂类型。上面显示的错误发生在 EF 已经错误地假定类型是实体但您尝试将其用作复杂类型时。在我看来,如果类没有关键属性,EF 不应该首先做出假设,但确实存在。解决方案是从OnModelCreating函数的开头简单地将其标记为复杂类型:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.ComplexType<Animal>();

    base.OnModelCreating(modelBuilder);
}

推荐阅读