首页 > Python资料 博客日记
【Entity Framework】EF中的增删改查
2024-08-11 00:00:12Python资料围观67次
【Entity Framework】EF中的增删改查
文章目录
一、概述
Entity Framework
是一个O/R Mapping的实例框架,前面的博文介绍了Entity Framework
的知识体系,本文将介绍EF基本使用,Entity Framework操作数据库,完成基本的增删改查。
二、DbContext数据上下文
DbContext
是Entity Framework
中的一个核心的类,它充当了应用程序和数据库之间的桥梁。DbContext
主要负责以下任务:
- 定义数据库上下文:DbContext包含与数据库连接相关的信息,例如数据库提供程序、连接字符串等。它也可以被视为一个数据库的代理,应用程序通过它来访问数据库。
- 定义实体映射:DbContext包含一个或多个DbSet,每个DbSet表示一个实体类型(通常是C#类)和数据库中的一个表。DbContext将实体类和数据库表之间的映射关系定义在一个模型中,这样就可以方便地进行数据的查询和操作。
- 执行SQL查询:当使用Entity Framework进行数据查询时,DbContext会将LINQ查询转换为SQL查询,并发送到数据库执行。
- 管理事务:DbContext提供了一个默认的事务管理器,用于管理数据库事务。在执行SaveChanges()方法时,事务自动提交或回滚。
- 更改跟踪:DbContext跟踪每个实体的状态,包括新增(added)、修改(modified)和删除(deleted)状态。这使得在执行SaveChanges()方法时,Entity Framework能够生成正确的SQL语句来更新数据库。
三、EntityState五个状态值
SavaChanged()用于提交数据,db.SaveChanged() 返回值是数据库中有几条数据被影响,所以你可以用db.SaveChanged()>0来判断是否成功插入,修改,删除数据。
当执行SaveChanged()方法执行期间,会根据EntityState的值,决定是去新增(Added)、修改(Modified)、删除(Deleted)。来执行操作。
db.Entry(userinfo).State = EntityState.Added;
序号 | 字段 | 值 | 说明 |
---|---|---|---|
1 | Added | 4 | 该对象是已添加到对象上下文的新对象,但尚未调用SaveChanges() 方法。在保持更改后,对象状态更改为Unchanged 。处于Added状态的对象在ObjectStateEntity中没有原始值。 |
2 | Deleted | 8 | 已从对象上下文中删除该对象,在保存更改后,对象状态更改为Detached 。 |
3 | Detached | 1 | 该对象在但未被跟踪。实体在创建之后且添加到对象上下文之前处于此状态。通过调用Detach(Object) 方法从上下文中移除实体后,或者使用NoTrackingMergeOption 加载实体后,该实体也会处于此状态。没有与处于ObjectStateEntry 状态对象关联的Detached 实体。 |
4 | Modified | 16 | 对象上的一个标量属性已修改,但尚未调用SaveChanges() 方法。在没有更改跟踪代理的POCO实体中,如果调用Modified 方法,则已修改属性的状态将更改为DetechChanges() 。保存更改后,对象状态更改为Unchanged 。 |
5 | Unchanged | 2 | 自附加到上下文中后,或自上次调用SaveChanges() 方法后,该对象尚未修改。 |
四、EF添加数据
要在数据源中插入数据时,必须创建实体类型的实例,并将该对象添加到对象上下文。 若要将新对象保存到数据源中,必须先设置不支持 null 值的所有属性。 使用实体框架 生成的类时,考虑使用实体类型的静态 Create
对象名称 方法创建实体类型的新实例。 实体数据模型 工具生成实体类型时,会在每个类中包含此方法。 此创建方法用于创建对象的实例并设置此类的不能为 null 的所有属性。 此方法对于在 CSDL 文件中已应用 Nullable="false"
特性的每个属性都包含一个参数。
4.1 EF Add方式
RbacDBEntities db = new RbacDBEntities();
Role r1 = new Role()
{
Name = “方式1”,
Remark = “备注1”
};
db.Roles.Add(r1);
db.SaveChanges();
4.2 EF 通过改变对象的状态为 Added
Role r2 = new Role()
{
Name = “方式2”,
Remark = “备注2”
};
db.Entry(r2).State = System.Data.Entity.EntityState.Added;
db.SaveChanges();
4.3 调用方sql
string sql = @“insert into roles values(‘方式3’,‘备注3’)”;
db.Database.ExecuteSqlCommand(sql);
db.SaveChanges();
4.4 调用存储过程
db.cp_insert_role(“方法4”, “备注4”);
Console.Read();
可以使用以下方法之一将新对象添加到对象上下文中:
ObjectSet
的AddObject
方法。ObjectContext
的AddObject
方法EntityCollection
的Add
方法。对于实体框架生成的实体和代理对象,在附加主体对象时也会将添加的实体附加到上下文中,调用DetectChanges
方法时将附件POCO实体。
在添加新对象时需要考虑下列注意事项:
- 调用 SaveChanges 之前,实体框架 会为每个新对象生成一个临时的键值。 调用 SaveChanges 后,该键值会被插入新行时数据源所指定的标识值所取代。
- 如果数据源未生成实体的键值,应指定一个唯一值。 如果两个对象具有相同的用户指定键值,则在调用 SaveChanges 时会发生
InvalidOperationException
。如果发生此问题,应指定唯一值并重试该操作。
五、EF修改数据
5.1 不查询数据库,主键必须赋值
为避免先查询数据库,可以直接将被修改的实体对象,添加到EF中管理,并手动设置其为未修改状态(Unchanged),同时设置被修改的实体对象的包装类对象对应属性为修改状态。
优点: 修改前不需要查询数据库
- 创建修改的实体对象
UserInfoes userInfonew = new UserInfoes()
{
UserId=userInfo.UserId,
Email = userInfo.Email,
FirstName = userInfo.FirstName,
LastName = userInfo.LastName,
LastUpdateBy = GetCurrentUserGuid(),
LastUpdate = DateTime.Now
};
- 添加到EF管理容器中
如果使用Entry附加实体对象到数据容器中,则需要手动设置实体包装类的对象的状态为Unchanged,或使用Attach(Attach方法:将给定实体以 System.Data.EntityState.Unchanged 状态附加到上下文中从解释可以看出Attach方法主要目的就是把一个没有被dbContext跟踪的对象附加到dbCotext中使其被dbContext跟踪)。
db.Entry(userInfonew).State = System.Data.Entity.EntityState.Unchanged;
或者
db.UserInfoes.Attach(userInfonew);
-
更新字段
- 更新全部字段
db.Entry(userInfonew).State = EntityState.Modified;
- 更新部分字段
db.Entry(userInfonew).Property(x => x.Email).IsModified = true;
-
更新到数据库
db.SaveChanges();
特别提醒:主键必须赋值,如果不赋值,会报错“Store update,insert or delete statement affected an unexpected number of rows(0)”
5.2 先查询实体再更新
-
查询实体后更新数据库
- 先查询要修改的原数据(注意此处不要加AsNoTracking(),加了无法更新)
var userInfoes= db.UserInfoes.Where(a => a.UserId== model.UserId).FirstOrDefault();
- 更新字段的值
userInfoes.LastUpdateBy = GetCurrentUserGuid(); userInfoes.LastUpdate = DateTime.Now;
- 更新到数据库
db.SaveChanges();
注意:EF查询出来的实体是无法更新主键的值
-
查询实体后不使用查询的实体,手动创建实体
var query = await (from a in db.MesMachineConfig
join c in db.Site_LinePosition
on new {A = a.LineNum,B = a.MCPosition} equals new {A= c.LineNum,B=c.MCPosition}
join b in db.DGHKROneReelNumManagerParamsSettings on a.MachineNum equals b.MachineNum into rightRow
from rw in rightRow.DefaultIfEmpty()
where a.Enable == "Y" && a.Size == dghkrOneReelNumManagerParamsSettingsDto.Size
select new {a,rw}
Attach的时候会报如下错误:因为相同类型的其他实体已具有相同的主键值。在使用 “Attach” 方法或者将实体的状态设置为 “Unchanged” 或 “Modified” 时如果图形中的任何实体具有冲突键值,则可能会发生上述行为。
六、EF删除数据
6.1 先查询数据,再根据查询的对象 ,删除对象
var delSysUser = accountContext.SysUsers.FirstOrDefault(m.m.Id==userId)
if(delSysUser==null)
{
accountContext.SysUsers.Remove(delSysUser);
}
var i = accountContext.SaveChanges();
6.2 自己创建对象,后附件,然后执行删除
SysUser delSysUser = new SysUser(){Id = delId};
accountContext.SysUsers.Attach(delSysUser);
accountContext.SysUsers.Remove(delSysUser);
var i = accountContext.SaveChanges();
6.3 自己创建对象,然后放入EF容器,然后删除
SysUser delSysUser=new SysUser(){Id = delId};
DbEntityEntry<SysUser> entityEntry = accountContext.Entry(delSysUser);
entityEntry.State = EntityState.Deleted;
var i = accountContext.SaveChanges();
标签:
相关文章
最新发布
- 【Python】selenium安装+Microsoft Edge驱动器下载配置流程
- Python 中自动打开网页并点击[自动化脚本],Selenium
- Anaconda基础使用
- 【Python】成功解决 TypeError: ‘<‘ not supported between instances of ‘str’ and ‘int’
- manim边学边做--三维的点和线
- CPython是最常用的Python解释器之一,也是Python官方实现。它是用C语言编写的,旨在提供一个高效且易于使用的Python解释器。
- Anaconda安装配置Jupyter(2024最新版)
- Python中读取Excel最快的几种方法!
- Python某城市美食商家爬虫数据可视化分析和推荐查询系统毕业设计论文开题报告
- 如何使用 Python 批量检测和转换 JSONL 文件编码为 UTF-8
点击排行
- 版本匹配指南:Numpy版本和Python版本的对应关系
- 版本匹配指南:PyTorch版本、torchvision 版本和Python版本的对应关系
- Python 可视化 web 神器:streamlit、Gradio、dash、nicegui;低代码 Python Web 框架:PyWebIO
- 相关性分析——Pearson相关系数+热力图(附data和Python完整代码)
- Python与PyTorch的版本对应
- Anaconda版本和Python版本对应关系(持续更新...)
- Python pyinstaller打包exe最完整教程
- Could not build wheels for llama-cpp-python, which is required to install pyproject.toml-based proj