EntityFrameWork Core从零开始,(九)继承影射的补充

本文探讨了在Entity Framework Core中如何实现单表和多表继承映射,通过实例对比了动物类及其子类的映射,并展示了如何在DbContext中管理和操作这些实体。重点在于理解不同方式对数据库表结构的影响和操作方式的不同。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:
继承影射其实也可以作为实体关系的一种,
但使用的地方明显比较少一些.
在Hibernate中,
继承映射主要有两种方式
1.单表继承映射
2.多表继承映射
当然比较好用的是单表继承映射,(只需要设置一个鉴别器属性即可),总体比较简单

EFCore的继承映射也分为这两种情况,分别是单表和多表
但不同的是
按照约定,EF 不会自动扫描基类型或派生类型;这意味着,如果要映射层次结构中的 CLR 类型,就必须在模型上显式指定该类型。 例如,仅指定层次结构的基类型不会导致 EF Core 隐式包含其所有子类型。(通俗一点说就是把所有的父类,子类都放到一个DbSet中放到DbContext里)

一.单表继承映射

以动物之间的关系为例

//基类
class Animal
{
     public int id { get; set; }
     public string name { get; set; }
}
//子类:鱼
class Fish:Animal
{
     public int flags;
 }
 //子类:狗
 class dog : Animal
{
    public int feet { get; set; }

    public string owner { get; set; }
}
//子类:熊
class Bear:Animal
{
    public string woodName { get; set; }

    public double wegiht { get; set; }
}

数据库上下文:

class ExtendDbContext:DbContext
{
     //将基类和子类都放在DbContext中
     public DbSet<Animal> animals { get; set; }

     public DbSet<dog> dogs { get; set; }

     public DbSet<Fish> fishes { get; set; }

     public DbSet<Bear> bears { get; set; }

     protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
     {
         var Connection = "server=XX;Database=XXX;uid=XXX;pwd=XXX";
         optionsBuilder.UseSqlServer(Connection);
     }

 }

输入

add-migration initialcreate -c ExtendDbContext
update-database -Context ExtendDbContext

成功的话进入迁移文件的建表代码

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.CreateTable(
        name: "animals",
        columns: table => new
        {
            id = table.Column<int>(type: "int", nullable: false)
                .Annotation("SqlServer:Identity", "1, 1"),
            name = table.Column<string>(type: "nvarchar(max)", nullable: true),
            //自动创建了鉴别器字段
            Discriminator = table.Column<string>(type: "nvarchar(max)", nullable: false),

            //下面都是子类的特有属性
            woodName = table.Column<string>(type: "nvarchar(max)", nullable: true),
            wegiht = table.Column<double>(type: "float", nullable: true),
            feet = table.Column<int>(type: "int", nullable: true),
            owner = table.Column<string>(type: "nvarchar(max)", nullable: true)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_animals", x => x.id);
        });
}

默认EFCore是单表继承映射,它会默认生成一个鉴别器字段在表中同时也是一个影子属性
表结构:
在这里插入图片描述
插入两条数据试试看

static void Main(string[] args)
{
     //繼承映射測試Demo
     ExtendDbContext context = new ExtendDbContext();
     dog d1 = new dog();
     d1.name = "旺財";
     d1.owner = "jotaro";
     d1.feet = 4;

     Bear xionger = new Bear();
     xionger.name = "熊二";
     xionger.woodName = "西伯利亞";
     xionger.wegiht = 400.00;

     context.dogs.Add(d1);
     context.bears.Add(xionger);
     context.SaveChanges();
 }

)
(单表继承映射与普通映射的区别是单表继承映射把一张表映射并维护成多个对象)

(PS.鉴别器字段也可以在FluentAPI中指定,虽然没有必要)

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property("Discriminator")
        .HasMaxLength(200);
}

二.多表继承映射

//多表继承的基类
class Computer
{
    public String id { get; set; }

    public String CPU { get; set; }

    public int RAM { get; set; }
}
//多表继承的子类
class laptop:Computer
{
    public String LAPTOP_Screen { get; set; }

    public String ModeID { get; set; }
}
class PC:Computer
{
    public String PC_Screen { get; set; }

    public String PC_box { get; set; }
}

数据库上下文:

class ExtendDbContextSec : DbContext
{
    public DbSet<Computer> computers { get; set; }
    
    public DbSet<PC> PCs { get; set; }

    public DbSet<laptop> laptops { get; set; }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var Connection = "server=XX;Database=XXX;uid=XX;pwd=XXXX";
        optionsBuilder.UseSqlServer(Connection);
    }

    //多表繼承映射只需要在FluentAPI里为每一种实体指定一张数据表即可
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Computer>().ToTable("t_computer");
        modelBuilder.Entity<laptop>().ToTable("t_laptop");
        modelBuilder.Entity<PC>().ToTable("t_pcs");
    }
}

同样查看一下建表语句:

protected override void Up(MigrationBuilder migrationBuilder)
{
      //创建基类表
     migrationBuilder.CreateTable(
         name: "t_computer",
         columns: table => new
         {
             id = table.Column<string>(type: "nvarchar(450)", nullable: false),
             CPU = table.Column<string>(type: "nvarchar(max)", nullable: true),
             RAM = table.Column<int>(type: "int", nullable: false)
         },
         constraints: table =>
         {
             table.PrimaryKey("PK_t_computer", x => x.id);
         });
     //创建子类表
     migrationBuilder.CreateTable(
         name: "t_laptop",
         columns: table => new
         {
             id = table.Column<string>(type: "nvarchar(450)", nullable: false),
             LAPTOP_Screen = table.Column<string>(type: "nvarchar(max)", nullable: true),
             ModeID = table.Column<string>(type: "nvarchar(max)", nullable: true)
         },
         //自动添加主键,同时也作为外键参考t_computer的主键
         constraints: table =>
         {
             table.PrimaryKey("PK_t_laptop", x => x.id);
             table.ForeignKey(
                 name: "FK_t_laptop_t_computer_id",
                 column: x => x.id,
                 principalTable: "t_computer",
                 principalColumn: "id",
                 onDelete: ReferentialAction.Restrict);
         });
     //创建子类表
     migrationBuilder.CreateTable(
         name: "t_pcs",
         columns: table => new
         {
             id = table.Column<string>(type: "nvarchar(450)", nullable: false),
             PC_Screen = table.Column<string>(type: "nvarchar(max)", nullable: true),
             PC_box = table.Column<string>(type: "nvarchar(max)", nullable: true)
         },
         //自动添加主键,同时也作为外键参考t_computer的主键
         constraints: table =>
         {
             table.PrimaryKey("PK_t_pcs", x => x.id);
             table.ForeignKey(
                 name: "FK_t_pcs_t_computer_id",
                 column: x => x.id,
                 principalTable: "t_computer",
                 principalColumn: "id",
                 onDelete: ReferentialAction.Restrict);
         });
 }

数据库表结构:
在这里插入图片描述
测试:

static void Main(string[] args)
        {
            ExtendDbContextSec contextSec = new ExtendDbContextSec();

            laptop rog = new laptop();
            rog.CPU = "i7-11800h";
            rog.RAM = 32;
            rog.LAPTOP_Screen = "300hz";
            rog.ModeID = "XHX";

            PC taishi = new PC();
            taishi.CPU = "i9-12900k";
            taishi.RAM = 16;
            taishi.PC_box = "alien";
            taishi.PC_Screen = "AOC XXXXX";

            contextSec.PCs.Add(taishi);
            contextSec.laptops.Add(rog);
            contextSec.SaveChanges();
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罗马苏丹默罕默德

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值