当前位置: 首页 > news >正文

【Entity Framework】聊一聊EF中继承关系

【Entity Framework】聊一聊EF中继承关系

文章目录

  • 【Entity Framework】聊一聊EF中继承关系
    • 一、概述
    • 二、实体类型层次结构映射
    • 三、每个层次结构一张表和鉴别器配置
    • 四、共享列
    • 五、每个类型一张表配置
    • 六、每个具体类型一张表配置
    • 七、TPC数据库架构
    • 八、总结

在这里插入图片描述

一、概述

Entity Framework可以将.NET类型层次结构映射到数据库。这允许你像普通编程一样使用基类型和派生类型在代码中编写.NET实体,并让Entity Framework无缝创建适应的数据库架构,发出查询等。有关如何映射类型层次结构的实际细节取决于提供程序;本博文将介绍关系数据库上下文中的继承支持。

二、实体类型层次结构映射

按照约定,Entity Framework不会自动扫描基类型或派生类型;如果要映射层次结构中的CLR类型,就必须在模型上显式指定该类型。如,仅指定层次结构的基类型不会导致EF Core隐式包含其所有子类型。

示例将为Blog及其子类RssBlog公开DbSet。如果Blog有任何其他子类,它不会包含在模型中。

internal class MyContext : DbContext
{public DbSet<Blog> Blogs { get; set; }public DbSet<RssBlog> RssBlogs { get; set; }
}public class Blog
{public int BlogId { get; set; }public string Url { get; set; }
}public class RssBlog : Blog
{public string RssUrl { get; set; }
}

使用TPH映射时,数据库会根据需要自动设置为可为null。如,RssUrl列可为null,因为常规Blog实例没有该属性。

三、每个层次结构一张表和鉴别器配置

默认情况下,EF使用每个层次结构一张表(TPH)模式来映射继承。(TPH)使用单个表来存储层次结构中所有类型的数据,并使用鉴别器列来识别每行表示的类型。

上面的模型映射到以下数据库架构(注意隐式创建的Discriminiator列,它标识了每行中存储的Blog类型)。

BlogIdUrlRssUrl
1Bloghttps://blog.csdn.net/songjianlongNULL
2RssBloghttps://blog.csdn.net/songjianlong

可以配置鉴别器列的名称和类型以及用于标识层次结构中每种类型的值:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{modelBuilder.Entity<Blog>().HasDiscriminator<string>("blog_type").HasValue<Blog>("blog_base").HasValue<RssBlog>("blog_rss");
}

在上面的示例中,EF在层次结构的基本实体上隐式添加了鉴别器作为影子属性。

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

最后,鉴别器也可以映射到实体中的常规.NET属性:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{modelBuilder.Entity<Blog>().HasDiscriminator(b => b.BlogType);modelBuilder.Entity<Blog>().Property(e => e.BlogType).HasMaxLength(200).HasColumnName("blog_type");modelBuilder.Entity<RssBlog>();
}

查询使用 TPH 模式的派生实体时,EF Core 会在查询中添加一个基于鉴别器列的谓词。 此筛选器确保对于结果中没有的基类型或同级类型,我们不会获得任何附加行。 对于基本实体类型,将跳过此筛选器谓词,因为查询基本实体将获得层次结构中所有实体的结果。 在具体化查询结果时,如果遇到未映射到模型中任何实体类型的鉴别器值,我们将引发异常,因为我们不知道如何具体化结果。 仅当数据库包含的行具有鉴别器值并且这些值未映射到 EF 模型时,才会发生此错误。 如果你有这样的数据,可以将 EF Core 模型中的鉴别器映射标记为不完整,以指示我们应始终添加筛选器谓词来查询层次结构中的任意类型。 IsComplete(false) 在鉴别器配置上调用会将映射标记为不完整。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{modelBuilder.Entity<Blog>().HasDiscriminator().IsComplete(false);
}

四、共享列

默认情况下,当层次结构中的两个同级实体类型具有同名的属性时,它们将映射到两个单独的列。 但是,如果它们的类型相同,则可以映射到相同的数据库列:

public class MyContext : DbContext
{public DbSet<BlogBase> Blogs { get; set; }protected override void OnModelCreating(ModelBuilder modelBuilder){modelBuilder.Entity<Blog>().Property(b => b.Url).HasColumnName("Url");modelBuilder.Entity<RssBlog>().Property(b => b.Url).HasColumnName("Url");}
}
public abstract class BlogBase
{public int BlogId { get; set; }
}
public class Blog : BlogBase
{public string Url { get; set; }
}
public class RssBlog : BlogBase
{public string Url { get; set; }
}

使用强制转换查询共享列时,关系数据库提供程序(例如 SQL Server)不会自动使用鉴别器谓词。 查询 Url = (blog as RssBlog).Url 还将返回同级 Blog 行的 Url 值。 若要将查询限制为 RssBlog 实体,你需要在鉴别器上手动添加筛选器,例如 Url = blog is RssBlog ? (blog as RssBlog).Url : null

五、每个类型一张表配置

在 TPT 映射模式中,所有类型都分别映射到各自的表。 仅属于某个基类型或派生类型的属性存储在映射到该类型的一个表中。 映射到派生类型的表还会存储外键来联接派生表与基表。

modelBuilder.Entity<Blog>().ToTable("Blogs");
modelBuilder.Entity<RssBlog>().ToTable("RssBlogs");

可以对每个根实体类型调用modelBuilder.Entity<Blog>().UseTptMappingStrategy(),而不是对每个实体类型调用ToTable,表名将由EF生成。

EF 将为上述模型创建以下数据库架构:

CREATE TABLE [Blogs] ([BlogId] int NOT NULL IDENTITY,[Url] nvarchar(max) NULL,CONSTRAINT [PK_Blogs] PRIMARY KEY ([BlogId])
);CREATE TABLE [RssBlogs] ([BlogId] int NOT NULL,[RssUrl] nvarchar(max) NULL,CONSTRAINT [PK_RssBlogs] PRIMARY KEY ([BlogId]),CONSTRAINT [FK_RssBlogs_Blogs_BlogId] FOREIGN KEY ([BlogId]) REFERENCES [Blogs] ([BlogId]) ON DELETE NO ACTION);

如果重命名主键约束,新名词将应用于映射到层次结构的所有表。未来的EF版本将允许仅对特定表重命名约束。

六、每个具体类型一张表配置

在TPC映射模式中,所有类型都分别映射到各自的表。每张表都包含相应实体类型上所有属性的列。这解决了TPT策略的一些常见性能问题。

modelBuilder.Entity<Blog>().UseTpcMappingStrategy().ToTable("Blogs");
modelBuilder.Entity<RssBlog>().ToTable("RssBlogs");

无需对每个实体类型调用 ToTable,只需对每个根实体类型调用 modelBuilder.Entity<Blog>().UseTpcMappingStrategy() 即可按照约定生成表名。

七、TPC数据库架构

TPC策略类类似与TPT策略,除了为层次结构中每个具体类型创建不同的表,但表不是为抽象类型创建的,因此名称为“每个具体类型一张表”。与TPT一样,表本身指示已保存对象的类型。但是,与TPT映射不同,每个表都包含具体类型及其基类型中没个属性的列。TPC数据库架构是非规范化的

八、总结

TPH 通常适用于大多数应用程序,并且对于各种方案而言都是一个很好的默认值,因此,如果不需要 TPC,请不要添加 TPC 来增加复杂性。 具体而言,如果代码主要查询许多类型的实体,例如针对基类型编写查询,则倾向于使用 TPH,而不是 TPC。

尽管如此,当代码主要查询单个叶类型的实体并且你基准测试显示与 TPH 相比有所改进时,TPC 也是一种很好的映射策略。

仅当受外部因素约束时,才使用 TPT。

相关文章:

【Entity Framework】聊一聊EF中继承关系

【Entity Framework】聊一聊EF中继承关系 文章目录 【Entity Framework】聊一聊EF中继承关系一、概述二、实体类型层次结构映射三、每个层次结构一张表和鉴别器配置四、共享列五、每个类型一张表配置六、每个具体类型一张表配置七、TPC数据库架构八、总结 一、概述 Entity Fra…...

curaengine编译源码之libarcus编译记录

libArcus的编译&#xff08;成功安装&#xff09; This library contains C code and Python3 bindings for creating a socket in a thread and using this socket to send and receive messages based on the Protocol Buffers library. It is designed to facilitate the c…...

运用OSI模型提升排错能力

1. OSI模型有什么实际的应用价值&#xff1f; 2. 二层和三层网络的区别和应用&#xff1b; 3. 如何通过OSI模型提升组网排错能力&#xff1f; -- OSI - 开放式系统互联 - 一个互联标准 - 从软件和硬件 定义标准 - 不同厂商的设备 研发的技术 - 具备兼容性 -- O…...

【Node.js】Express学习笔记(黑马)

目录 初识 ExpressExpress 简介Express 的基本使用托管静态资源nodemon Express 路由路由的概念路由的使用 Express 中间件中间件的概念Express 中间件的初体验中间件的分类 初识 Express Express 简介 什么是 Express&#xff1f; 官方给出的概念&#xff1a;Express 是基于…...

Linux系统部署Tale个人博客并发布到公网访问

目录 ⛳️推荐 前言 1. Tale网站搭建 1.1 检查本地环境 1.2 部署Tale个人博客系统 1.3 启动Tale服务 1.4 访问博客地址 2. Linux安装Cpolar内网穿透 3. 创建Tale博客公网地址 4. 使用公网地址访问Tale ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通…...

CentOS7里ifcfg-eth0文件不存在解决方案/Centos7修改网络IP解决方案

Centos7网络IP地址手动设置 1、centos7没有ifcfg-eth0&#xff0c;我的centos7也没有其他博客说的什么ifcfg-ens33、ifcfg-ens32&#xff0c;然后我打开了我这里的ifcfg-eno***&#xff0c;结果发现就是centos6里的ifcfg-eth0里的网络配置。2、vim ifcfg-eno***&#xff08;按t…...

go第三方库go.uber.org介绍

Uber 是一家美国硅谷的科技公司&#xff0c;也是 Go 语言的早期 adopter。其开源了很多 golang 项目&#xff0c;诸如被 Gopher 圈熟知的 zap、jaeger 等。2018 年年末 Uber 将内部的 Go 风格规范 开源到 GitHub&#xff0c;经过一年的积累和更新&#xff0c;该规范已经初具规模…...

Oracle 正则表达式

一、Oracle 正则表达式相关函数 (1) regexp_like &#xff1a;同 like 功能相似&#xff08;模糊 匹配&#xff09; (2) regexp_instr &#xff1a;同 instr 功能相似&#xff08;返回字符所在 下标&#xff09; (3) regexp_substr &#xff1a; 同 substr 功能相似&…...

MongoDB聚合运算符:$rand

MongoDB聚合运算符&#xff1a;$rand 文章目录 MongoDB聚合运算符&#xff1a;$rand语法举例生成随机数据点从集合中随机选择条目 $rand聚合运算符用于返回一个0~1之间的随机浮点数。 语法 { $rand: {} }$rand运算符不需要任何参数。每次调用$rand都会返回一个小数点后最多17位…...

如何在Linux通过docker搭建Plik文件系统并实现无公网IP管理内网文件

文章目录 1. Docker部署Plik2. 本地访问Plik3. Linux安装Cpolar4. 配置Plik公网地址5. 远程访问Plik6. 固定Plik公网地址7. 固定地址访问Plik 本文介绍如何使用Linux docker方式快速安装Plik并且结合Cpolar内网穿透工具实现远程访问&#xff0c;实现随时随地在任意设备上传或者…...

k8s部署efk

环境简介&#xff1a; kubernetes: v1.22.2 helm&#xff1a; v3.12.0 elasticsearch&#xff1a; 8.8.0 chart包&#xff1a;19.10.0 fluentd: 1.16.2 chart包&#xff1a; 5.9.4 kibana: 8.2.2 chart包&#xff1a;10.1.9 整体架构图&#xff1a; 一、Elasticsearch安装…...

AI模型大PK

&#x1f916;AI模型大PK&#xff01;免费测试GPT-4等36款顶级聊天机器人 近年来&#xff0c;大型语言模型&#xff08;LLM&#xff09;的发展日新月异&#xff0c;各大科技巨头和研究机构纷纷推出了自己的聊天机器人。那么&#xff0c;如何才能知道哪个模型更强大、更智能呢&…...

Matlab|基于广义Benders分解法的综合能源系统优化规划

目录 1 主要内容 广义benders分解法流程图&#xff1a; 优化目标&#xff1a; 约束条件&#xff1a; 2 部分代码 3 程序结果 4 下载链接 1 主要内容 该程序复现文章《综合能源系统协同运行策略与规划研究》第四章内容基于广义Benders分解法的综合能源系统优化规划&…...

vscode 打代码光标特效

vscode 打代码光标特效 在设置里面找到settings 进入之后在代码最下方加入此代码 "explorer.confirmDelete": false,"powermode.enabled": true, //启动"powermode.presets": "fireworks", // 火花效果// particles、 simple-rift、e…...

【代码随想录算法训练营第四十八天 | LeetCode198.打家劫舍、213.打家劫舍II、337.打家劫舍III】

代码随想录算法训练营第四十八天 | LeetCode198.打家劫舍、213.打家劫舍II、337.打家劫舍III 一、198.打家劫舍 解题代码C&#xff1a; class Solution { public:int rob(vector<int>& nums) {if (nums.size() 0) return 0;if (nums.size() 1) return nums[0];ve…...

蓝桥杯 — —灵能传输

灵能传输 友情链接&#xff1a;灵能传输 题目&#xff1a; 输入样例&#xff1a; 3 3 5 -2 3 4 0 0 0 0 3 1 2 3输出样例&#xff1a; 3 0 3思路&#xff1a; 题目大意&#xff1a;给出一个数组&#xff0c;每次选择数组中的一个数&#xff08;要求不能是第一个数与最后一个…...

智慧安防系统EasyCVR视频汇聚平台接入大华设备无法语音对讲的原因排查与解决

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台支持7*24小时实时高清视频监控&#xff0c;能同时播放多路监控视频流&#xff0c;视频画面1、4、9、16个可选&#xff0c;支持自定义视频轮播。EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标…...

基于Pytorch框架的CNN-LSTM模型在CWRU轴承故障诊断的应用

目录 1. 简介 2. 方法 2.1数据集 2.2模型架构 1. 简介 CWRU轴承故障诊断是工业领域一个重要的问题&#xff0c;及早发现轴承故障可以有效地减少设备停机时间和维修成本&#xff0c;提高生产效率和设备可靠性。传统的基于信号处理和特征提取的方法通常需要手工设计特征&…...

QQ 邮箱使用 SMTP 发送邮件报错:550 The From header is missing or invalid

文章目录 场景描述问题排查根据提示查看原因查看封装的 message 个人简介 场景描述 QQ 邮箱使用 SMTP 发送邮件报错&#xff1a;550 The From header is missing or invalid&#xff1a; 失败原因&#xff1a;(550, bThe "From" header is missing or invalid. Ple…...

mysql中的视图

1、什么是视图&#xff1f; view:站在不同的角度去看待同一份数据。 2、怎么创建视图对象&#xff1f;怎么删除视图对象&#xff1f; 表复制&#xff1a; mysql> create table dept2 as select * from dept; 创建视图对象&#xff1a; create view dept2_v…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

Rust 开发环境搭建

环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行&#xff1a; rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu ​ 2、Hello World fn main() { println…...

基于鸿蒙(HarmonyOS5)的打车小程序

1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...