2

EF7继承映射 - YataoFeng

 1 year ago
source link: https://www.cnblogs.com/YataoFeng/p/17181056.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Entity Framework 7 (EF7)中的继承映射允许您将类层次结构映射到数据库中的表层次结构。具体而言,这意味着您可以创建一个基类,然后从该基类派生多个子类,并将这些子类映射到不同的数据库表。这使得在数据库中存储不同类型的数据变得更加方便,同时还能保持面向对象编程的优雅性。
EF7提供了三种类型的继承映射:单表继承(Table Per Hierarchy,TPH)、分层表继承(Table Per Type,TPT)和单独的表继承(Table Per Concrete Class,TPC)。下面分别介绍这三种映射类型。
性能基准

单表继承映射(Table Per Hierarchy,TPH)

单表继承映射将整个类层次结构映射到单个数据库表中。每个类在表中对应一行,其中包括一个用于区分不同子类的Discriminator列。例如,考虑以下类层次结构:

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

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

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

使用单表继承映射,可以将这个类层次结构映射到以下数据库表:

+----+-------+-----+-------+------------+------------+
| Id | Name  | Age | Breed | IsIndoor   | Discriminator |
+----+-------+-----+-------+------------+------------+
| 1  | Fido  | 3   | Poodle| NULL       | Dog          |
+----+-------+-----+-------+------------+------------+
| 2  | Felix | 5   | NULL  | true       | Cat          |
+----+-------+-----+-------+------------+------------+

可以看到,每个Animal子类都在同一个表中表示为一行,并使用Discriminator列进行区分。
要使用TPH映射,在EF7中,可以使用Fluent API进行配置,如下所示:

modelBuilder.Entity<Animal>()
    .HasDiscriminator<string>("Discriminator")
    .HasValue<Dog>("Dog")
    .HasValue<Cat>("Cat");

这个代码片段将Animal类设置为基类,然后使用HasDiscriminator方法指定Discriminator列的名称。接下来,使用HasValue方法为每个Animal子类指定一个值,以便在Discriminator列中进行区分。

分层表继承映射(Table Per Type,TPT)

分层表继承映射将基类和每个子类映射到不同的数据库表中。每个子类的表都包含基类的所有列和子类特有的列。例如,对于上述类层次结构,使用分层表继承映射,可以将Animal、Dog和Cat分别映射到三个不同的表中:

Animal table:
+----+-------+-----+
| Id | Name  | Age |
+----+-------+-----+
| 1  | Fido  | 3   |
+----+-------+-----+
| 2  | Felix | 5   |
+----+-------+-----+

Dog table:
+----+-------+-----+-------+
| Id | Name  | Age | Breed |
+----+-------+-----+-------+
| 1  | Fido  | 3   | Poodle|
+----+-------+-----+-------+

Cat table:
+----+-------+-----+----------+
| Id | Name  | Age | IsIndoor |
+----+-------+-----+----------+
| 2  | Felix | 5   | true     |
+----+-------+-----+----------+

可以看到,每个表都只包含基类和对应的子类的列。每个子类表还包含一个外键,指向基类表的主键。
要使用TPT映射,在EF7中,可以使用Fluent API进行配置,如下所示:

modelBuilder.Entity<Animal>()
    .ToTable("Animals");

modelBuilder.Entity<Dog>()
    .ToTable("Dogs")
    .HasOne(a => a.Animal)
    .WithOne()
    .HasForeignKey<Dog>(d => d.Id);

modelBuilder.Entity<Cat>()
    .ToTable("Cats")
    .HasOne(a => a.Animal)
    .WithOne()
    .HasForeignKey<Cat>(c => c.Id);

这个代码片段中,Animal被映射到Animals表中。对于每个Animal子类,使用ToTable方法将其映射到相应的表中。在每个子类表中,使用HasOne方法指定一个导航属性,表示它与基类表中的一行相关联。使用HasForeignKey方法指定外键属性和基类表中的主键。

单独的表继承映射(Table Per Concrete Class,TPC)

单独的表继承映射将每个类都映射到一个独立的数据库表中。每个表都只包含该类的列。这意味着基类和子类之间没有直接的关系。例如,对于上述类层次结构,使用单独的表继承映射,可以将Animal、Dog和Cat分别映射到三个不同的表中:

Animal table:
+----+-------+-----+
| Id | Name  | Age |
+----+-------+-----+
| 1  | Fido  | 3   |
+----+-------+-----+
| 2  | Felix | 5   |
+----+-------+-----+

Dog table:
+----+-------+-----+-------+
| Id | Name  | Age | Breed |
+----+-------+-----+-------+
| 1  | Fido  | 3   | Poodle|
+----+-------+-----+-------+
    
Cat table:
+----+-------+-----+----------+
| Id | Name  | Age | IsIndoor |
+----+-------+-----+----------+
| 2  | Felix | 5   | true     |
+----+-------+-----+----------+

要使用TPC映射,在EF7中,可以使用Fluent API进行配置,如下所示:

modelBuilder.Entity<Animal>()
    .ToTable("Animals");

modelBuilder.Entity<Dog>()
    .ToTable("Dogs");

modelBuilder.Entity<Cat>()
    .ToTable("Cats");

这个代码片段中,每个类都被映射到不同的表中,使用ToTable方法指定表名。

继承映射的查询

在EF7中,使用继承映射时,可以查询基类和子类的实例。例如,以下代码查询所有动物的名字:

using (var context = new AnimalContext())
{
    var names = context.Set<Animal>()
        .Select(a => a.Name)
        .ToList();
}

这个查询将返回Animal表和所有子类表中的所有名称。如果要只查询特定类型的动物,可以在查询中使用OfType方法,例如:

using (var context = new AnimalContext())
{
    var dogNames = context.Set<Animal>()
        .OfType<Dog>()
        .Select(d => d.Name)
        .ToList();
}

这个查询只返回Dog表中的名称。

继承映射是一种重要的ORM技术,允许将类层次结构映射到数据库表层次结构中。EF7支持三种继承映射策略:分层表继承映射、单独的表继承映射和联合表继承映射。使用Fluent API可以很容易地配置这些映射。在查询数据时,可以使用OfType方法筛选出特定类型的实例。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK