【Entity Framework】 EF三种开发模式
【Entity Framework】 EF三种开发模式
文章目录
- 【Entity Framework】 EF三种开发模式
- 一、概述
- 二、DataBase First
- 2.1 DataBase First简介
- 2.2 DataBase First应用步骤
- 2.3 DataBase First总结
- 三、Model First
- 3.1 Model First简介
- 3.2 Model First实现步骤
- 四、Code First
- 4.1 Code First概述
- 4.2 Code First实现步骤
- 4.3 Code First的映射规则

一、概述
前面博文已介绍了Entity Framework是什么,EF
架构等基本知识介绍。本文将从介绍Entity Framework使用的三种方式。
Entity Framework的底层其实是调用ADO.NET
,它是更高层次的封装,作为数据访问的技术。Entity Framework设计的高扩展性,体现在灵活的映射定义。简单的说,使用Entity Framework可以充分定义与数据库表映射的实体,这个实体可以直接用于业务逻辑层或作为服务的数据契约。使用EF后,可以将实体类的设计工作完全放在EDM设计过程中,而不需要手工写哪些大同小异的代码,令人欣喜的是这个实体模型可以在运行时修改并生效,我们开发时也不用再频繁地与数据库打交道。只要通过操作实体模型就能完成对数据库的操作。
EF框架可以划分一下三种应用模式:
- DataBase First
- Model First
- Code First
下面将详细介绍下面三种模式
二、DataBase First
DataBase First参考
2.1 DataBase First简介
Database First就是先建数据库或使用已有的数据库。然后再vs中添加ADO.Net实体数据模型,设置连接并且选择需要的数据库和表。它是以数据库设计为基础的,并根据数据库自动生成实体数据模型,从而驱动整个开发流程。除生成实体模型和自跟踪实现模型,还支持生成轻型DbContext。这种模式的好处是使用简单,容易上手。比较适合于采用已经存在的数据库进行开发。既通过简单的方式实现了,又重用了数据库。
2.2 DataBase First应用步骤
如果使用DataBase First模式,先创建好对应的数据库及表。
- 现在项目->添加新项->选择
ADO.NET实体数据模型
。 - 打开启动实体数据模型向导,选择“从数据库生成”,并创建数据库连接字符串。
- 单击“表”旁边的复选框以导入所有表,然后单击“完成”
2.3 DataBase First总结
Database First开发,它允许我们基于现有数据库在EF设计器中创建模型。然后,我们使用该模型在数据库中读取和写入一些数据。
三、Model First
3.1 Model First简介
Model First
允许你使用实体框架设计器创建新模型,然后从该模型生成数据库架构。 模型存储在 EDMX
文件(.edmx
扩展名)中,可以在实体框架设计器中查看和编辑。 你在应用程序中与之交互的类是从 EDMX
文件自动生成的。
3.2 Model First实现步骤
- 使用 Visual Studio 中包含的实体框架设计器来创建模型
- “项目” ->“添加新项…”
- 从左侧菜单中选择“数据”,然后选择"ADO.NET实体数据模型"
- 输入“xxxModel”名称并单击确定,这将启动实体数据模型向导
- 选择“空模型”并单击“完成”
- 向模型添加实体、属性和关联
- 右键单击设计图面并选择“属性”
- 在“属性”窗口中,将“实体容器名称”更改为 xxxContext。这是将为你生成的派生上下文的名称,该上下文表示与数据库的会话,允许我们查询和保存数据
- 右键单击设计图面并选择“添加新项”->“实体…”
- 输入 Blog 作为实体名称,输入 BlogId 作为键名称,然后单击“确定”
- 右键单击设计图面上的新实体并选择“添加新项”->“标量属性”,输入 Name 作为属性名称。
- 重复此过程以添加 URL 属性。
- 右键单击设计图面上的 URL 属性并选择“属性”,在“属性”窗口中将“可为 null” 设置更改为 True。这样,我们无需为 Blog 分配 URL 即可将其保存到数据库中
- 添加关联(或关系)
- 右键单击设计图面并选择“添加新项”->“关联…”
- 使关系的一端指向 Blog,多重性为“一”,另一端指向 Post,多重性为“多”。这意味着一个 Blog 有多个 Post,而一个 Post 属于一个 Blog
- 确保选中“将外键属性添加到“Post”实体”框,然后单击“确定”
四、Code First
4.1 Code First概述
Code First模式我们称之为“代码优先”模式,从某种角度来看,其实“Code First”和“Model First”区别并不是太明显,只是它不借助于实体数据模型设计器,而是直接通过编码方式设计实体模型(这也是为什么最开始“Code First”被叫做“Code Only”的原因)。但是对于EF它的处理过程有所差别,例如我们使用Code First就不再需要EDM文件,所有的映射通过“数据注释”和“fluent API”进行映射和配置。
4.2 Code First实现步骤
- 添加类创建实体模型,并创建导航属性,设置实体模型之间关系。
- 安装Entity Framework包
- 通过NuGet在线安装Entity Framework包
- 使用"程序包管理器控制台"通过"Install-package EntityFramework"命令安装
- 创建dbContext上下文
- 首先在配置文件中(app.config)中配置数据库链接字符串
- 接下来创建dbContext类,此类继承System.Data.Entity.DbContext类,其构造函数调用了积累带参数的构造函数,用来读取配置文件中的数据库链接字符串。
- 对数据进行增删改查操作
- 使用dbContext对象对数据库进行操作
4.3 Code First的映射规则
-
关于表和字段名的约定
Code First约定表名使用实体类名的复数形式来命名表明,属性映射的列使用与类中属性一致的名字命名
-
关于主键的约定
Code First默认规定将命名为Id或[类名]Id的属性是为类的主键,如果是int类型或GUID类型同时会设为标识列。
-
关于字符串属性的约定
Code First将String类型属性映射为不限长度的非空列中。默认数据类型为
nvarchar(max)
,且允许为空。 -
关于布尔属性的约定
Code First将bool类型属性映射为bit类型,且不允许为空
-
关于外键的约定
对于外键,如果在类中添加了引用类型,而这个引用类型也在Entity Framework的上下文中,EF会把这种属性成为导航属性。
一旦EF在类中检索到导航属性,就会寻找对应的外键。EF会认为属性名+Id或者类名+Id可能就是外键属性,如果找到名称一致且类型与导航属性目标类的主键类型一致,则认为是外键。如果类型不一致,EF则会认为该类设置有误。
如果没有找到符合要求的属性,EF会自己添加一个外键属性。另外,对于不同的关系也有一些不同的约定。
- 一对一关系:要求导航属性双方都应该具有外键配置。
- 一对多关系:要求多的一方设置外键。同时如果在一方这边设置了集合类型的导航属性,那么EF会自动到目标类中寻找外键属性。
- 多对多关系:会生成一个中间关系表。
相关文章:

【Entity Framework】 EF三种开发模式
【Entity Framework】 EF三种开发模式 文章目录 【Entity Framework】 EF三种开发模式一、概述二、DataBase First2.1 DataBase First简介2.2 DataBase First应用步骤2.3 DataBase First总结 三、Model First3.1 Model First简介3.2 Model First实现步骤 四、Code First4.1 Cod…...
数据分析---SQL(5)
目录 子查询单行子查询多行子查询视图(View)创建视图使用视图更新视图视图的优缺点存储过程存储过程的创建存储过程的参数存储过程的优缺点可能导致性能问题避免存储过程引入性能问题子查询 子查询是指在一个查询语句中嵌套另一个查询语句,内部的查询语句称为子查询,外部的…...

《剑指 Offer》专项突破版 - 面试题 93 : 最长斐波那契数列(C++ 实现)
题目链接:最长斐波那契数列 题目: 输入一个没有重复数字的单调递增的数组,数组中至少有 3 个数字,请问数组中最长的斐波那契数列的长度是多少?例如,如果输入的数组是 [1, 2, 3, 4, 5, 6, 7, 8]࿰…...

代码随想录算法训练营第五十五天|583. 两个字符串的删除操作、72. 编辑距离
583. 两个字符串的删除操作 刷题https://leetcode.cn/problems/delete-operation-for-two-strings/description/文章讲解https://programmercarl.com/0583.%E4%B8%A4%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E5%88%A0%E9%99%A4%E6%93%8D%E4%BD%9C.html视频讲解https://…...
StringRedisTemplate Autowired注入为空解决
如下注入方式报空指针异常: java.lang.NullPointerException: null Autowiredprivate StringRedisTemplate redisTemplate; 解决办法:查看该类上有没有加注解,如Component等,没加的话加上。 还有一种是在工具类中使用,…...

c语言:文件操作
1. 为什么使⽤⽂件? 如果没有⽂件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失 了,等再次运⾏程序,是看不到上次程序的数据的,如果要将数据进⾏持久…...

C#事件实例详解
一、什么是事件? 在C#中,事件(event)是一种特殊的类成员,它允许类或对象通知其他类或对象发生了某些事情。 从语法上看,事件的声明类似于字段,但它们在功能和行为上有一些重要的区别。 从技术角度来说,事件实际上是一个封装了事件订阅和取消订阅功能的委托字段。…...

零基础机器学习(3)之机器学习的一般过程
文章目录 一、机器学习一般过程1.数据获取2.特征提取3.数据预处理①去除唯一属性②缺失值处理A. 均值插补法B. 同类均值插补法 ③重复值处理④异常值⑤数据定量化 4.数据标准化①min-max标准化(归一化)②z-score标准化(规范化) 5.…...
用java做一个双色球彩票系统
代码如下: import java.util.Random; public class HelloWorld{public static void main(String[] args){//1、生成中奖号码 int[] arrcreateNumber();for (int i 0;i<arr.length;i) {System.out.print(arr[i]" ");}}public static int[] createNu…...

某对象存储元数据集群改造流水账
软件产品:某厂商提供的不便具名的对象存储产品,核心底层技术源自HDFS和Amazon S3,元数据集群采用了基于MongoDB的NOSQL数据库产品和MySQL数据库产品相结合。 该产品的元数据逻辑示意图如下: 业务集群现状:当前第3期建…...
前端理论总结(js)——filter、foearch、for in 、for of 、for的区别以及返回值
Filter: 用途:用于筛选数组中符合条件的元素,返回一个新数组。 返回值:返回一个新数组,包含经过筛选的元素。 Foreach: 用途:遍历数组中的每个元素,执行回调函数。 返回值&#x…...

【JavaEE初阶系列】——多线程案例一——单例模式 (“饿汉模式“和“懒汉模式“以及解决线程安全问题)
目录 🚩单例模式 🎈饿汉模式 🎈懒汉模式 ❗线程安全问题 📝加锁 📝执行效率提高 📝指令重排序 🍭总结 单例模式,非常经典的设计模式,也是一个重要的学科&#x…...

革新水库大坝监测:传统软件与云平台之比较
在水库大坝的监测管理领域,传统监测软件虽然曾发挥了重要作用,但在多方面显示出了其局限性。传统解决方案通常伴随着高昂的运维成本,需要大量的硬件支持和人员维护,且软件整合和升级困难,限制了其灵活性和扩展性。 点击…...

C++模版(基础)
目录 C泛型编程思想 C模版 模版介绍 模版使用 函数模版 函数模版基础语法 函数模版原理 函数模版实例化 模版参数匹配规则 类模版 类模版基础语法 C泛型编程思想 泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。 模板是泛型编程…...

MySQL驱动Add Batch优化实现
MySQL 驱动 Add Batch 优化实现 MySQL 驱动会在 JDBC URL 添加 rewriteBatchedStatements 参数时,对 batch 操作进行优化。本文测试各种参数组合的行为,并结合驱动代码简单分析。 batch参数组合行为 useServerPrepStmts 参数 PreparedStatement psmt…...

手撕算法-数组中的第K个最大元素
描述 分析 使用小根堆,堆元素控制在k个,遍历数组构建堆,最后堆顶就是第K个最大的元素。 代码 class Solution {public int findKthLargest(int[] nums, int k) {// 小根堆PriorityQueue<Integer> queue new PriorityQueue<>…...
【vue】computed和watch的区别和应用场景
Computed 和 Watch 是 Vue.js 中用于监视数据变化的两个不同特性,它们各自有不同的应用场景和功能。 Computed: 计算属性(Computed properties)用于声明基于其他数据属性的计算值。它具有缓存功能,只有在依赖的数…...
ARM.day8
1.自己设置温度湿度阈值,当温度过高时,打开风扇,蜂鸣器报警 2.当湿度比较高时,打开LED1灯,蜂鸣器报警 main.c #include "si7006.h" #include "CH1.h" #include "led.h" // 延时函数in…...

SpringCloud Gateway工作流程
Spring Cloud Gateway的工作流程 具体的流程: 用户发送请求到网关 请求断言,用户请求到达网关后,由Gateway Handler Mapping(网关处理器映射)进行Predicates(断言),看一下哪一个符合…...

西井科技与安通控股签署战略合作协议 共创大物流全新生态
2024年3月21日,西井科技与安通控股在“上海硅巷”新象限空间正式签署战略合作框架协议。双方基于此前在集装箱物流的成功实践与资源优势,积极拓展在AI数字化产品、新能源自动驾驶解决方案和多场景应用,以及绿色物流链等领域的深度探索、强强联…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...

使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
go 里面的指针
指针 在 Go 中,指针(pointer)是一个变量的内存地址,就像 C 语言那样: a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10,通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...