翼度科技»论坛 编程开发 .net 查看内容

EF7继承映射

4

主题

4

帖子

12

积分

新手上路

Rank: 1

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

单表继承映射将整个类层次结构映射到单个数据库表中。每个类在表中对应一行,其中包括一个用于区分不同子类的Discriminator列。例如,考虑以下类层次结构:
  1. public abstract class Animal
  2. {
  3.     public int Id { get; set; }
  4.     public string Name { get; set; }
  5.     public int Age { get; set; }
  6. }
  7. public class Dog : Animal
  8. {
  9.     public string Breed { get; set; }
  10. }
  11. public class Cat : Animal
  12. {
  13.     public bool IsIndoor { get; set; }
  14. }
复制代码
使用单表继承映射,可以将这个类层次结构映射到以下数据库表:
  1. +----+-------+-----+-------+------------+------------+
  2. | Id | Name  | Age | Breed | IsIndoor   | Discriminator |
  3. +----+-------+-----+-------+------------+------------+
  4. | 1  | Fido  | 3   | Poodle| NULL       | Dog          |
  5. +----+-------+-----+-------+------------+------------+
  6. | 2  | Felix | 5   | NULL  | true       | Cat          |
  7. +----+-------+-----+-------+------------+------------+
复制代码
可以看到,每个Animal子类都在同一个表中表示为一行,并使用Discriminator列进行区分。
要使用TPH映射,在EF7中,可以使用Fluent API进行配置,如下所示:
  1. modelBuilder.Entity<Animal>()
  2.     .HasDiscriminator<string>("Discriminator")
  3.     .HasValue<Dog>("Dog")
  4.     .HasValue<Cat>("Cat");
复制代码
这个代码片段将Animal类设置为基类,然后使用HasDiscriminator方法指定Discriminator列的名称。接下来,使用HasValue方法为每个Animal子类指定一个值,以便在Discriminator列中进行区分。
分层表继承映射(Table Per Type,TPT)

分层表继承映射将基类和每个子类映射到不同的数据库表中。每个子类的表都包含基类的所有列和子类特有的列。例如,对于上述类层次结构,使用分层表继承映射,可以将Animal、Dog和Cat分别映射到三个不同的表中:
  1. Animal table:
  2. +----+-------+-----+
  3. | Id | Name  | Age |
  4. +----+-------+-----+
  5. | 1  | Fido  | 3   |
  6. +----+-------+-----+
  7. | 2  | Felix | 5   |
  8. +----+-------+-----+
  9. Dog table:
  10. +----+-------+-----+-------+
  11. | Id | Name  | Age | Breed |
  12. +----+-------+-----+-------+
  13. | 1  | Fido  | 3   | Poodle|
  14. +----+-------+-----+-------+
  15. Cat table:
  16. +----+-------+-----+----------+
  17. | Id | Name  | Age | IsIndoor |
  18. +----+-------+-----+----------+
  19. | 2  | Felix | 5   | true     |
  20. +----+-------+-----+----------+
复制代码
可以看到,每个表都只包含基类和对应的子类的列。每个子类表还包含一个外键,指向基类表的主键。
要使用TPT映射,在EF7中,可以使用Fluent API进行配置,如下所示:
  1. modelBuilder.Entity<Animal>()
  2.     .ToTable("Animals");
  3. modelBuilder.Entity<Dog>()
  4.     .ToTable("Dogs")
  5.     .HasOne(a => a.Animal)
  6.     .WithOne()
  7.     .HasForeignKey<Dog>(d => d.Id);
  8. modelBuilder.Entity<Cat>()
  9.     .ToTable("Cats")
  10.     .HasOne(a => a.Animal)
  11.     .WithOne()
  12.     .HasForeignKey<Cat>(c => c.Id);
复制代码
这个代码片段中,Animal被映射到Animals表中。对于每个Animal子类,使用ToTable方法将其映射到相应的表中。在每个子类表中,使用HasOne方法指定一个导航属性,表示它与基类表中的一行相关联。使用HasForeignKey方法指定外键属性和基类表中的主键。
单独的表继承映射(Table Per Concrete Class,TPC)

单独的表继承映射将每个类都映射到一个独立的数据库表中。每个表都只包含该类的列。这意味着基类和子类之间没有直接的关系。例如,对于上述类层次结构,使用单独的表继承映射,可以将Animal、Dog和Cat分别映射到三个不同的表中:
  1. Animal table:
  2. +----+-------+-----+
  3. | Id | Name  | Age |
  4. +----+-------+-----+
  5. | 1  | Fido  | 3   |
  6. +----+-------+-----+
  7. | 2  | Felix | 5   |
  8. +----+-------+-----+
  9. Dog table:
  10. +----+-------+-----+-------+
  11. | Id | Name  | Age | Breed |
  12. +----+-------+-----+-------+
  13. | 1  | Fido  | 3   | Poodle|
  14. +----+-------+-----+-------+
  15.    
  16. Cat table:
  17. +----+-------+-----+----------+
  18. | Id | Name  | Age | IsIndoor |
  19. +----+-------+-----+----------+
  20. | 2  | Felix | 5   | true     |
  21. +----+-------+-----+----------+
复制代码
要使用TPC映射,在EF7中,可以使用Fluent API进行配置,如下所示:
  1. modelBuilder.Entity<Animal>()
  2.     .ToTable("Animals");
  3. modelBuilder.Entity<Dog>()
  4.     .ToTable("Dogs");
  5. modelBuilder.Entity<Cat>()
  6.     .ToTable("Cats");
复制代码
这个代码片段中,每个类都被映射到不同的表中,使用ToTable方法指定表名。
继承映射的查询

在EF7中,使用继承映射时,可以查询基类和子类的实例。例如,以下代码查询所有动物的名字:
  1. using (var context = new AnimalContext())
  2. {
  3.     var names = context.Set<Animal>()
  4.         .Select(a => a.Name)
  5.         .ToList();
  6. }
复制代码
这个查询将返回Animal表和所有子类表中的所有名称。如果要只查询特定类型的动物,可以在查询中使用OfType方法,例如:
  1. using (var context = new AnimalContext())
  2. {
  3.     var dogNames = context.Set<Animal>()
  4.         .OfType<Dog>()
  5.         .Select(d => d.Name)
  6.         .ToList();
  7. }
复制代码
这个查询只返回Dog表中的名称。
总结

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

来源:https://www.cnblogs.com/YataoFeng/archive/2023/03/05/17181056.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具