EF6(Entity Framework 6)基础知识

一、Entity Framework 6 概述

Entity Framework (EF) 是 Microsoft 提供的一个对象关系映射器 (ORM),它使得 .NET 开发人员能够使用 .NET 对象来处理数据库,从而无需经常编写大部分数据访问代码。EF 提供了许多功能,包括更改跟踪、查询构建、视图生成和映射存储过程等。

Entity Framework 6 (EF6) 是 Entity Framework 的一个版本,它在 Entity Framework 5 的基础上进行了许多改进和优化,提供了更高效的查询性能、更灵活的配置选项以及更好的可扩展性。

二、定义 DbContext 派生类

在 EF6 中,DbContext 是与数据库交互的主要类。它表示一个数据库上下文,用于包含 DbSet 属性,这些属性表示数据库中的表或视图。下面是一个简单的示例,演示如何定义一个派生自 DbContext 的类:

using System.Data.Entity;  namespace MyApp.DataModels  
{  public class MyDbContext : DbContext  {  public MyDbContext() : base("name=MyConnectionString") { }  public DbSet<Category> Categories { get; set; }  public DbSet<Product> Products { get; set; }  // 其他 DbSet 属性...  }  
}

在这个例子中,MyDbContext 类继承自 DbContext,并定义了两个 DbSet 属性:Categories 和 Products。这些属性分别表示数据库中的 Categories 表和 Products 表。构造函数中的 base("name=MyConnectionString") 指定了用于连接到数据库的连接字符串的名称,该名称通常在应用的配置文件(如 App.config 或 Web.config)中定义。

三、使用 DbContext 进行数据库操作 

一旦定义了 DbContext 派生类,就可以使用它来执行各种数据库操作,如查询、添加、更新和删除实体。

1. 查询实体

要查询数据库中的实体,可以访问 DbContext 上的 DbSet 属性。这不会立即执行查询,而是创建一个可执行的查询对象。当实际需要数据时(例如,在遍历查询结果或在调用如 ToListToArray 等方法时),查询才会执行。

using (var context = new MyDbContext())  
{  // 查询所有类别  var allCategories = context.Categories.ToList();  // 查询具有特定名称的产品  var productByName = context.Products.FirstOrDefault(p => p.Name == "ProductName");  
}

2. 添加实体

要向数据库添加新实体,可以使用 DbSet 的 Add 方法。添加后,需要调用 SaveChanges 方法来将更改提交到数据库。

using (var context = new MyDbContext())  
{  var newCategory = new Category { Name = "NewCategory" };  context.Categories.Add(newCategory);  context.SaveChanges(); // 提交更改到数据库  
}

3. 更新实体

要更新数据库中的现有实体,首先需要将实体从数据库中检索出来,修改其属性,然后调用 SaveChanges 方法。EF6 会跟踪实体的更改,并只更新发生更改的属性。

using (var context = new MyDbContext())  
{  var categoryToUpdate = context.Categories.Find(categoryId); // 假设 categoryId 是要更新的类别的 ID  if (categoryToUpdate != null)  {  categoryToUpdate.Name = "UpdatedCategoryName";  context.SaveChanges(); // 提交更改到数据库  }  
}

4. 删除实体

要从数据库中删除实体,可以使用 DbSet 的 Remove 方法。同样,需要调用 SaveChanges 方法来提交删除操作。

using (var context = new MyDbContext())  
{  var categoryToDelete = context.Categories.Find(categoryId); // 假设 categoryId 是要删除的类别的 ID  if (categoryToDelete != null)  {  context.Categories.Remove(categoryToDelete);  context.SaveChanges(); // 提交删除操作到数据库  }  
}

四、处理导航属性和外键

在 EF6 中,实体之间的关系可以通过导航属性和外键来表示。导航属性是指向其他实体的引用,而外键是用于在数据库中维护关系的字段。EF6 会自动处理这些关系的同步。

例如,假设 Product 实体有一个导航属性 Category,表示产品所属的类别,并且有一个外键 CategoryId。当将一个产品添加到 Products DbSet 并设置其 Category 属性时,EF6 会自动处理 CategoryId 的设置。同样,当谈到处理导航属性和外键时,Entity Framework 6 (EF6) 提供了强大的支持来管理实体之间的关系。导航属性使得你可以通过对象模型直接访问关联的其他实体,而无需显式地处理外键。

以下是一个示例,展示了如何在实体类中使用导航属性和外键,并在 DbContext 中进行相应的配置:

using System.ComponentModel.DataAnnotations;  
using System.ComponentModel.DataAnnotations.Schema;  
using System.Data.Entity;  namespace MyApp.DataModels  
{  public class Category  {  [Key]  public int CategoryId { get; set; }  public string Name { get; set; }  // 导航属性,指向属于此类别的所有产品  public virtual ICollection<Product> Products { get; set; }  }  public class Product  {  [Key]  public int ProductId { get; set; }  public string Name { get; set; }  public decimal Price { get; set; }  // 外键属性,指向此产品所属的类别  public int CategoryId { get; set; }  // 导航属性,指向此产品所属的类别对象  public virtual Category Category { get; set; }  }  public class MyDbContext : DbContext  {  public MyDbContext() : base("name=MyConnectionString") { }  public DbSet<Category> Categories { get; set; }  public DbSet<Product> Products { get; set; }  // 配置模型(可选),例如指定外键和级联删除等  protected override void OnModelCreating(DbModelBuilder modelBuilder)  {  modelBuilder.Entity<Product>()  .HasRequired(p => p.Category) // 指定 Category 是必需的  .WithMany(c => c.Products) // 并与 Categories 中的 Products 集合关联  .HasForeignKey(p => p.CategoryId); // 指定外键属性  // 其他配置...  }  }  
}

 

在这个例子中,Product 类有一个 CategoryId 属性作为外键,指向 Category 类。同时,它也有一个 Category 导航属性,这是一个 Category 类型的对象,使得你可以方便地访问与产品关联的类别信息。

在 MyDbContext 类的 OnModelCreating 方法中,你可以使用 DbModelBuilder 来进一步配置实体之间的关系。在这个例子中,我们使用 HasRequired 和 WithMany 方法来配置 Product 和 Category 之间的多对一关系,并指定 CategoryId 作为外键。

五、DbContext 的高级功能

 除了基本的 CRUD 操作外,EF6 还提供了许多高级功能,可以帮助你更有效地处理数据库操作。

 一、延迟加载

延迟加载是Entity Framework中的一项特性,它允许在需要时才从数据库中加载相关的数据。具体来说,当访问一个实体的导航属性时,Entity Framework不会立即加载与该导航属性相关的数据,而是等到真正需要这些数据时才去数据库查询。这种方式可以有效减少数据库查询的次数,从而提高性能。

延迟加载的实现依赖于动态代理技术。当Entity Framework启用延迟加载时,它会为实体类生成一个动态代理类,这个代理类会覆盖导航属性的访问器,实现延迟加载的逻辑。因此,在使用延迟加载时,导航属性通常会被标记为virtual,以允许Entity Framework创建代理类。

需要注意的是,延迟加载虽然方便,但也可能导致N+1查询问题。即当遍历一个包含多个实体的集合时,如果每个实体都通过延迟加载访问其导航属性,那么将会对数据库发起多次查询,从而导致性能下降。因此,在使用延迟加载时,需要谨慎考虑其可能带来的影响。

二、异步操作

传统的同步操作会阻塞调用线程,直到操作完成才返回结果。而异步操作则允许调用线程在等待操作完成时继续执行其他任务,从而提高应用程序的吞吐量和响应速度。

Entity Framework提供了许多异步操作的方法,如SaveChangesAsyncToListAsync等。这些方法会返回一个TaskTask<T>对象,表示异步操作的任务。调用这些方法的线程可以继续执行其他任务,而不必等待数据库操作完成。当数据库操作完成时,Task对象会触发完成事件,此时可以获取操作的结果。

使用异步操作需要注意以下几点:

  1. 异步方法应该与异步上下文一起使用,例如在ASP.NET Core的控制器中,应该使用asyncawait关键字来调用异步方法。
  2. 异步方法不应该被阻塞调用,即不应该使用ResultWait方法来等待异步操作完成,这样会导致异步操作的优势失效。
  3. 需要注意异常处理,确保异步操作中的异常能够被正确捕获和处理。

三、查询优化

优化查询可以减少数据库的负担,提高查询速度,从而提升应用程序的性能。

以下是一些常见的查询优化技术:

  1. 投影查询:只选择需要的列,避免查询多余的列。这可以减少数据传输的量和数据库的工作负担。
  2. 使用索引:为经常查询的列创建索引,可以加快查询速度。但需要注意,过多的索引会增加数据库的维护成本,因此需要权衡利弊。
  3. 避免N+1查询:如前所述,延迟加载可能导致N+1查询问题。可以通过显式加载(Eager Loading)或显式指定查询的关联数据来避免这个问题。
  4. 编写高效的LINQ查询:避免在LINQ查询中使用复杂的逻辑和不必要的计算,尽量让数据库完成查询工作。
  5. 监控和分析:使用Entity Framework的性能分析工具和数据库监控工具来识别性能瓶颈和优化点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/24.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于springboot的房屋租赁系统源码数据库

基于springboot的房屋租赁系统源码数据库 摘 要 社会的发展和科学技术的进步&#xff0c;互联网技术越来越受欢迎。网络计算机的生活方式逐渐受到广大人民群众的喜爱&#xff0c;也逐渐进入了每个用户的使用。互联网具有便利性&#xff0c;速度快&#xff0c;效率高&#xf…

苹果开发初学者指南:Xcode 如何为运行的 App 添加环境变量(Environmental Variable)

概览 Xcode 15 在运行 SwiftUI 代码时突然报告如下警告&#xff1a; Error: this application, or a library it uses, has passed an invalid numeric value (NaN, or not-a-number) to CoreGraphics API and this value is being ignored. Please fix this problem. 不仅如此…

Linux:PCIe的capability扩展空间字段解释

以下为PCIe的截图示例 [rootngnodeb ~]# lspci -vvv -d 8086:0d5c 1b:00.0 Processing accelerators: Intel Corporation Device 0d5c (prog-if 01) Subsystem: Intel Corporation Device 0000 Control: I/O- Mem BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- St…

windows10下Linux子系统(ubuntu22.04) sshd docker kubectl helm

sshd 每次开机之后&#xff0c;启动sshd操作如下 mkdir /run/sshd /usr/sbin/sshd下载安装docker wget https://download.docker.com/linux/static/stable/x86_64/docker-20.10.6.tgz tar xf docker-20.10.6.tgz chown -R root.root docker cp docker/* /usr/bin/ groupadd …

react之useState详解

1. 为什么要用useState&#xff1f; 它是React 16.8 的新特性&#xff0c;我们在React里面一般都是用Class去写组件&#xff0c;但是有时候会发现不用它更方便&#xff0c;但是问题来了&#xff1a;不用Class的时候&#xff0c;数据的状态改变如何存储呢&#xff1f;如果你用 …

数据结构-堆详解

堆 图片&#xff1a; 二叉堆的父节点为这个子树的最值。 如何维护它。 我们发现它是一棵二叉树&#xff0c;那就自然满足若父节点为 x x x 则左儿子节点为 x 2 x\times2 x2 右儿子为 x 2 1 x\times 2 1 x21 这是显然的&#xff0c;但如果写成指针或结构体就太麻烦了&…

Redis的特性与安装

回顾 Redis是一个在内存中存储数据的中间件&#xff0c;可以用来当数据库用&#xff0c;也可以作为缓存用(这里的缓存往往是对数据库缓存)。 中间件&#xff1a;和业务无关的服务&#xff0c;功能更加通用&#xff0c;如&#xff1a;数据库&#xff0c;缓存&#xff0c;消息队…

【笔试强训】Day1 --- 数字统计 + 两个数组的交集 + 点击消除

文章目录 1. 数字统计2. 两个数组的交集3. 点击消除 1. 数字统计 【链接】&#xff1a;数字统计 解题思路&#xff1a;模拟&#xff0c;利用数学知识&#xff0c;计算每个数字中2出现的个数。&#xff08;这里也可以将数字转换成字符串来统计字符’2’出现的个数&#xff09…

C# 语言类型(五)—其他

总目录 C# 语法总目录 参考链接&#xff1a; C#语法系列:C# 语言类型(一)—预定义类型值之数值类型 C#语法系列:C# 语言类型(二)—预定义类型之字符串及字符类型简述 C#语法系列:C# 语言类型(三)—数组/枚举类型/结构体 C#语法系列:C# 语言类型(四)—传递参数及其修饰符 C#语法…

如何使用Flask搭建web程序框架并实现无公网IP远程访问本地程序

文章目录 前言1. 安装部署Flask并制作SayHello问答界面2. 安装Cpolar内网穿透3. 配置Flask的问答界面公网访问地址4. 公网远程访问Flask的问答界面 前言 Flask是一个Python编写的Web微框架&#xff0c;让我们可以使用Python语言快速实现一个网站或Web服务&#xff0c;本期教程…

模拟器无法ADB链接的所有情况及解决方案

前言&#xff1a; adb&#xff08;Android Debug Bridge&#xff09;安卓调试桥&#xff0c;简单可以理解为外部连接安卓内部的一个接口&#xff0c;走的是tcp协议。 但是在模拟器上面经常会遇到连不上adb&#xff0c;在此收集一下各种情况&#xff0c;想起来或者遇到了就更新…

bonding原理分析和问题排查

bonding原理 发送端&#xff1a; 使用网卡bond3模式&#xff08;广播模式BOND_MODE_BROADCAST&#xff09;将报文从两个网卡同时发出&#xff0c;无需修改报文。 接收端&#xff1a; 根据发送节点时间的链路通断状态&#xff0c;接收端设置一条线路为活动线&#xff0c;另一条…

免费泛域名SSL如何申请,和通配符有什么区别

-----让我们明确什么是泛域名。所谓泛域名&#xff0c;是指使用星号&#xff08;*&#xff09;作为子域名的占位符&#xff0c;它可以匹配任意子域名。-----而通配符在域名中&#xff0c;它可以出现在主域名的任何位置&#xff0c;它可以用于主域名和子域名的保护。 主要应用场…

XZ-Utils后门事件过程及启示

Part.01 背景 XZ-Utils&#xff08;曾经叫做LZMA Utils&#xff09;是一款开源的无损压缩命令行工具&#xff0c;是用C语言编写的跨平台工具&#xff0c;可以用于类Unix系统和Windows系统。在多数情况下&#xff0c;xz的压缩率要好过gzip和bzip2&#xff0c;解压速度也快过bz…

算法学习笔记——专题拓展2:数组双指针经典习题

关于数组的技巧有&#xff1a;双指针(快慢指针&#xff08;时差、位差&#xff09;&#xff09; 例题1&#xff1a;合并两个有序数组 代码&#xff1a;逆向双指针&#xff0c;可以不用重开数组&#xff0c;如果是正向的&#xff0c;需要重开一个数组腾空间。 class Solution …

图书借阅系统开发笔记

图书借阅系统开发介绍及心得 项目已开源到 github https://github.com/Qiu-JW/books-manage-systemgitee https://gitee.com/qiu-jw/books-manage-system 技术栈 前端 HTML5、CSS、JS、jQuery、axios、bootstrap 后端 servlet、JSP、JDBC 数据库 MySQL 项目采用mvc模式构成 …

Java的数组定义和使用

目录 1.前言 2.数组的概念 3.在Java中的创建和初始化 3.1数组的创建 3.2数组的初始化 4.关于使用 4.1数组元素的访问 4.2数组的遍历 4.3length和length()的区别 5.数组其实是引用类型数据 5.1初始JVM的内存分布 5.2基本类型变量与引用类型变量的区别 5.3关于null的认识 5.4设计…

手眼标定(外参)

1. 传统使用张正友相机标定,角点检测 //张正友相机标定,角点检测 for(int i=1;i<=images_number;i++){Mat image=imread(images_path+to_string(i)+String("/color.jpg"));Mat output=image.clone();image_size.width=image.cols;image_size.height=image.…

(34)4.17 作业课

//弓箭型 int main() { int n 0; while (scanf("%d", &n) 1) { int i 0; for (i 0; i < n; i) { int j 0; for (j 0; j < n - i; j) { printf(" &q…

工作流JBPM画图与配置

文章目录 ☃️7.1 画图☃️7.2 配置7.2.1 配置任务办理人7.2.1.1 写死的方式配置任务办理人&#xff08;不推荐&#xff09;7.2.1.2 #{}方式配置任务办理人7.2.1.3 实现接口方式配置任务办理人7.2.1.4 方法指定方式分配任务办理人 7.2.2 配置节点属性7.2.2.1 判断节点(decision…