📜  Entity Framework-继承(1)

📅  最后修改于: 2023-12-03 15:14:52.831000             🧑  作者: Mango

Entity Framework 继承

在 Entity Framework 中,继承是一个常见的模式,它允许从一个模型中创建出另一个模型,并且使继承的模型能够自动继承基本模型的属性和行为。本文将介绍 Entity Framework 中的继承模式,并提供一些示例。

Table per Hierarchy(TPH)

Table per Hierarchy(TPH)是最常见的 EF 继承模式之一。此模式使用单个表来存储层次结构中的所有实体,并区分它们的类型。每个实体类型都有一个标识列,该列用于区分层次结构中的不同实体类型。例如,我们有一个动物的继承层次结构,其中有四个类:Animal、Dog、Cat 和 Bird。

从 Animal 类派生的类,将 Animal 类和 Dog 类作为同一张表,在表中创建了一个 Name 列和一个 AnimalType 列,AnimalType 列指示着每一行数据属于哪种实体类型。其中,AnimalType 的值可以使用枚举来表示。下面是一个示例:

public enum AnimalType
{
    Animal = 0,
    Dog = 1,
    Cat = 2,
    Bird = 3
}

public class Animal
{
    public int Id { get; set; }
    public string Name { get; set; }
    public AnimalType AnimalType { get; set; }
}

public class Dog : Animal
{
    public string Breed { get; set; }
}

public class Cat : Animal
{
    public bool IsLazy { get; set; }
}

public class Bird : Animal
{
    public int WingSpan { get; set; }
}

在这个例子中,我们定义了一个用于表示 AnimalType 列的枚举。Animal 类是一个抽象类,有一个 AnimalType 属性,用于区分继承结构中的不同实体类型。Dog、Cat 和 Bird 从 Animal 类继承而来,并为每个实体类型添加了一个属性。

现在,我们需要将这些类映射到一个单独的表中,用于实现 Table per Hierarchy:

public class AnimalContext : DbContext
{
    public DbSet<Animal> Animals { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Animal>()
                    .Map<Dog>(m => m.Requires("AnimalType").HasValue((int)AnimalType.Dog))
                    .Map<Cat>(m => m.Requires("AnimalType").HasValue((int)AnimalType.Cat))
                    .Map<Bird>(m => m.Requires("AnimalType").HasValue((int)AnimalType.Bird));

        base.OnModelCreating(modelBuilder);
    }
}

在模型构建器中,我们可以使用 Map 方法映射 Animal 类型,将其映射到数据库中的单个表。在 Map 方法中,我们使用 Requires 方法为每个类型指定一个特定的 AnimalType 值。

现在,我们可以通过 AnimalContext 上下文对象查询和保存动物的不同类型。

Table per Type (TPT)

Table per Type(TPT) 是另一个常见的 EF 继承模式。此模式也使用多个表来存储层次结构中的实体,但不同之处在于每个实体类型都有自己的表。例如,我们有一个文档类型的继承层次结构,其中有两个类型:文本文档和图像文档。

public class Document
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string FileName { get; set; }
}

public class TextDocument : Document
{
    public string Content { get; set; }
}

public class ImageDocument : Document
{
    public byte[] ImageData { get; set; }
    public string ImageType { get; set; }
}

在这个例子中,我们定义了一个 Document 类,它有一个 Id、Name 和 FileName 属性,用于标识文档。TextDocument 和 ImageDocument 继承自 Document 类,并添加了它们自己的属性。

为了实现 Table per Type 模式,我们需要使用多个表来表示每个实体类型。在本例中,我们需要创建一个 Documents 表,一个 TextDocuments 表和一个 ImageDocuments 表:

public class DocumentContext : DbContext
{
    public DbSet<Document> Documents { get; set; }
    public DbSet<TextDocument> TextDocuments { get; set; }
    public DbSet<ImageDocument> ImageDocuments { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Document>()
                    .ToTable("Documents")
                    .HasKey(d => d.Id);

        modelBuilder.Entity<TextDocument>()
                    .ToTable("TextDocuments")
                    .HasKey(d => d.Id);

        modelBuilder.Entity<ImageDocument>()
                    .ToTable("ImageDocuments")
                    .HasKey(d => d.Id);

        base.OnModelCreating(modelBuilder);
    }
}

在模型构建器中,我们通过调用 Entity 方法并使用 ToTable 方法来让每个实体类型使用自己的表。我们也设置了每个实体类型的主键。

现在,我们可以通过 DocumentContext 上下文对象查询和保存不同类型的文档。

总结

继承是一种常见的程序设计模式,它在 Entity Framework 中也适用。在本文中,我们介绍了两种继承模式: Table per Hierarchy 和 Table per Type。 在这两种模式中,都有一些技术需要掌握,但它们可以简化模型,并且有助于保持代码的清晰。