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

(26)ASP.NET Core2.2 EF保存(基本保存、保存相关数据、级联删除、使用事务)

1.简介

每个上下文实例都有一个ChangeTracker,它负责跟踪需要写入数据库的更改。更改实体类的实例时,这些更改会记录在ChangeTracker中,然后在调用SaveChanges时会被写入数据库中。此数据库提供程序负责将更改转换为特定于数据库的操作(例如,关系数据库的INSERT、UPDATE和DELETE命令)。

2.基本保存

了解如何使用上下文和实体类添加、修改和删除数据。

2.1添加数据

使用DbSet.Add方法添加实体类的新实例。调用SaveChanges时,数据将插入到数据库中:

using (var context = new BloggingContext())
{var blog = new Blog { Url = "http://sample.com" };context.Blogs.Add(blog);context.SaveChanges();
}

2.2更新数据

EF将自动检测对由上下文跟踪的现有实体所做的更改。这包括从数据库加载查询的实体,以及之前添加并保存到数据库的实体。只需通过赋值来修改属性,然后调用SaveChanges即可:

using (var context = new BloggingContext())
{var blog = context.Blogs.First();blog.Url = "http://sample.com/blog";context.SaveChanges();
}

2.3删除数据

使用DbSet.Remove方法删除实体类的实例。如果实体已存在于数据库中,则将在SaveChanges期间删除该实体。如果实体尚未保存到数据库(即跟踪为“已添加”),则在调用SaveChanges时,该实体会从上下文中移除且不再插入:

using (var context = new BloggingContext())
{var blog = context.Blogs.First();context.Blogs.Remove(blog);context.SaveChanges();
}

2.4单个SaveChanges中的多个操作

可以将多个添加/更新/删除操作合并到对SaveChanges的单个调用:

using (var context = new BloggingContext())
{// addcontext.Blogs.Add(new Blog { Url = "http://sample.com/blog_one" });context.Blogs.Add(new Blog { Url = "http://sample.com/blog_two" });// updatevar firstBlog = context.Blogs.First();firstBlog.Url = "";// removevar lastBlog = context.Blogs.Last();context.Blogs.Remove(lastBlog);context.SaveChanges();
}

3.保存关联数据

除了独立实体以外,还可以使用模型中定义的关系。

3.1添加关联数据

如果创建多个新的相关实体,则将其中一个添加到上下文时也会添加其他实体。在下面的示例中,博客和三个相关文章会全部插入到数据库中。找到并添加这些文章,因为它们可以通过Blog.Posts导航属性访问:

using (var context = new BloggingContext())
{var blog = new Blog{Url = "http://blogs.msdn.com/dotnet",Posts = new List<Post>{new Post { Title = "Intro to C#" },new Post { Title = "Intro to VB.NET" },new Post { Title = "Intro to F#" }}};context.Blogs.Add(blog);context.SaveChanges();
}

3.2添加相关实体

如果从已由上下文跟踪的实体的导航属性中引用新实体,则将发现该实体并将其插入到数据库中。在下面的示例中,插入post实体,因为该实体会添加到已从数据库中提取的blog实体的Posts属性:

using (var context = new BloggingContext())
{var blog = context.Blogs.Include(b => b.Posts).First();var post = new Post { Title = "Intro to EF Core" };blog.Posts.Add(post);context.SaveChanges();
}

3.3更改关系

如果更改实体的导航属性,则将对数据库中的外键列进行相应的更改。在下面的示例中,post实体更新为属于新的blog实体,因为其Blog导航属性设置为指向blog,blog也会插入到数据库中,因为它是已由上下文post跟踪的实体的导航属性引用的新实体:

using (var context = new BloggingContext())
{//新增一个主体实体var blog = new Blog { Url = "http://blogs.msdn.com/visualstudio" };var post = context.Posts.First();//post更新关系post.Blog = blog;context.SaveChanges();
}

4.级联删除

删除行为在DeleteBehavior枚举器类型中定义,并且可以传递到OnDelete Fluent API来控制:
●可以删除子项/依赖项
●子项的外键值可以设置为null
●子项保持不变

示例:

var blog = context.Blogs.Include(b => b.Posts).First();
var posts = blog.Posts.ToList();
DumpEntities("  After loading entities:", context, blog, posts);
context.Remove(blog);
DumpEntities($"  After deleting blog '{blog.BlogId}':", context, blog, posts);
try
{Console.WriteLine();Console.WriteLine("  Saving changes:");context.SaveChanges();DumpSql();DumpEntities("  After SaveChanges:", context, blog, posts);
}
catch (Exception e)
{DumpSql();Console.WriteLine();Console.WriteLine($"  SaveChanges threw {e.GetType().Name}: {(e is DbUpdateException ? e.InnerException.Message : e.Message)}");
}

记录结果:

  After loading entities:Blog '1' is in state Unchanged with 2 posts referenced.Post '1' is in state Unchanged with FK '1' and reference to blog '1'.Post '2' is in state Unchanged with FK '1' and reference to blog '1'.After deleting blog '1':Blog '1' is in state Deleted with 2 posts referenced.Post '1' is in state Unchanged with FK '1' and reference to blog '1'.Post '2' is in state Unchanged with FK '1' and reference to blog '1'.Saving changes:DELETE FROM [Posts] WHERE [PostId] = 1DELETE FROM [Posts] WHERE [PostId] = 2DELETE FROM [Blogs] WHERE [BlogId] = 1After SaveChanges:Blog '1' is in state Detached with 2 posts referenced.Post '1' is in state Detached with FK '1' and no reference to a blog.Post '2' is in state Detached with FK '1' and no reference to a blog.

5.事务

事务允许以原子方式处理多个数据库操作。如果已提交事务,则所有操作都会成功应用到数据库。如果已回滚事务,则所有操作都不会应用到数据库。

5.1控制事务

可以使用DbContext.Database API开始、提交和回滚事务。以下示例显示了两个SaveChanges()操作以及正在单个事务中执行的LINQ查询。并非所有数据库提供应用程序都支持事务的。 调用事务API时,某些提供应用程序可能会引发异常或不执行任何操作:

using (var context = new BloggingContext())
{using (var transaction = context.Database.BeginTransaction()){try{context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });context.SaveChanges();context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/visualstudio" });context.SaveChanges();var blogs = context.Blogs.OrderBy(b => b.Url).ToList();// Commit transaction if all commands succeed, transaction will auto-rollback// when disposed if either commands failstransaction.Commit();}catch (Exception){// TODO: Handle failure}}
}

6.总结

由于工作繁忙原因,EF系列在这里也就完结了,暂时没有太多时间记录下去了。今天这个章节也偷了个懒,稍微精简一点,具体官方说明,我会在下面贴上的,请见谅。

参考文献:
基本保存https://learn.microsoft.com/zh-cn/ef/core/saving/basic
保存相关数据https://learn.microsoft.com/zh-cn/ef/core/saving/related-data
级联删除https://learn.microsoft.com/zh-cn/ef/core/saving/cascade-delete
使用事务https://learn.microsoft.com/zh-cn/ef/core/saving/transactions

http://www.dtcms.com/a/414554.html

相关文章:

  • 西昌新站seo太原网站建设方案开发
  • 永久个人网站网站开发 设计文档
  • 天拓四方集团IoT平台在金属表面处理行业的智能化转型实践
  • 00-1-正则表达式学习心得:从入门到上瘾,再到克制
  • 【性能测试之正则表达式】正则表达式零基础入门:从“抄”到“写”,附性能测试实战案例
  • python-poppler - PDF文档处理Python绑定库
  • Android开发-Handler消息机制记录
  • 通信专业知识图谱​
  • 网站建设的页面要求一级域名二级域名
  • 基础镜像清理策略在VPS环境存储优化中的维护规范
  • The 2025 ICPC South America - Brazil First Phase
  • 开源 C# 快速开发(六)自定义控件--圆环
  • Calico 网络插件在 K8s 集群的作用
  • 蓝桥杯13届省题
  • 手机网站开发+图库类怎样在手机上建设网站
  • MySQL三层架构:从连接管理到数据存储
  • 嵌入式硬件——IMX6ULL时钟配置
  • 【用androidx.camera拍摄景深合成照片】
  • linux安装google chrome 谷歌浏览器
  • 从零起步学习Redis || 第二章:Cache Aside Pattern(旁路缓存模式)以及优化策略
  • 两性做受技巧视频网站喊别人做的网站不肯给代码
  • ESP32-S3入门第八天:往期知识回顾与实战练习
  • Claude Code 实战指南(三):AI辅助开发工作流 Spec Workflow MCP教程
  • 红帽认证含金量怎么样?适合哪些人?
  • 宣传的网站开发需要多少钱步骤的英文
  • 选择一款拖拽式界面的vscode扩展程序制作Python界面
  • Android开发-屏幕变更事件
  • 十大咨询公司排行榜aso优化师主要是干嘛的
  • LeetCode第1346题 - 检查整数及其两倍数是否存在
  • 【Leetcode hot 100】207.课程表