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

EntityFramework Core笔记:保存数据(4)

1. 基本保存

  每个DBContext实例都有一个ChangeTracker,负责跟踪需要写入数据库的更改。当实例发生更改时,更改会被记录在ChangeTracker中,在调用 SaveChanges 时被写入数据库。

1.1 添加数据

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

using (var context = new LibingContext())
{
    var role = new Role
    {
        RoleName = "教师"
    };
    context.Roles.Add(role);

    context.SaveChanges();
}

1.2 更新数据

  Entity Framwork Core将自动检测对由DbContext跟踪的实体所做的更改。

  更新数据:修改属性值,调用 SaveChanges()。

using (var context = new LibingContext())
{
    var role = context.Roles.Find(1);
    role.RoleName = "教师";

    context.SaveChanges();
}

1.3 删除数据

  使用 DbSet.Remove() 删除实体类的实例。

  如果实体已存在于数据库中,则 SaveChanges() 将删除该实体。 如果实体尚未保存到数据库(即跟踪为“已添加”),则 SaveChanges() 时,该实体会从上下文中删除且不再插入。

using (var context = new LibingContext())
{
    var role = context.Roles.Find(1);
    context.Roles.Remove(role);

    context.SaveChanges();
}

1.4 一个SaveChanges 中的多个操作

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

  对于大多数数据库提供程序,“SaveChanges”是事务性的。

using (var context = new LibingContext())
{
    // 新增
    context.Roles.Add(new Role { RoleName = "管理员" });
    context.Roles.Add(new Role { RoleName = "学生" });

    // 修改
    var modifyRole = context.Roles.Find(1);
    modifyRole.RoleName = "教师";

    // 删除
    var deleteRole = context.Roles.Where(t => t.RoleID == 2).FirstOrDefault();
    context.Roles.Remove(deleteRole);

    context.SaveChanges();
}

2. 关联数据

2.1 添加新实体的关系图

using (var context = new LibingContext())
{                
    var category = new Category
    {
        CategoryName = "手机",
        Products = new List<Product> {
            new Product { ProductName = "华为", UnitPrice = 2000 },
            new Product { ProductName = "小米", UnitPrice = 1000 }
        }
    };
    context.Categories.Add(category);

    context.SaveChanges();
}
exec sp_executesql N'SET NOCOUNT ON;
INSERT INTO [Category] ([CategoryName])
VALUES (@p0);
SELECT [CategoryID]
FROM [Category]
WHERE @@ROWCOUNT = 1 AND [CategoryID] = scope_identity();

',N'@p0 nvarchar(4000)',@p0=N'手机'
exec sp_executesql N'SET NOCOUNT ON;
INSERT INTO [Product] ([CategoryID], [ProductName], [UnitPrice])
VALUES (@p0, @p1, @p2);
SELECT [ProductID]
FROM [Product]
WHERE @@ROWCOUNT = 1 AND [ProductID] = scope_identity();

',N'@p0 int,@p1 nvarchar(4000),@p2 decimal(4,0)',@p0=1,@p1=N'华为',@p2=2000
exec sp_executesql N'SET NOCOUNT ON;
INSERT INTO [Product] ([CategoryID], [ProductName], [UnitPrice])
VALUES (@p0, @p1, @p2);
SELECT [ProductID]
FROM [Product]
WHERE @@ROWCOUNT = 1 AND [ProductID] = scope_identity();

',N'@p0 int,@p1 nvarchar(4000),@p2 decimal(4,0)',@p0=1,@p1=N'小米',@p2=1000

2.2 添加关联实体

  如果从已由DbContext跟踪的实体的导航属性中引用新实体,则该实体将插入到数据库中。

using Microsoft.EntityFrameworkCore;
using (var context = new LibingContext())
{
    var category = context.Categories
        .Include(t => t.Products)
        .Where(t => t.CategoryID == 1)
        .FirstOrDefault();
    category.Products.Add(new Product
    {
        ProductName = "VIVO",
        UnitPrice = 1500
    });

    context.SaveChanges();
}
SELECT TOP(1) [t].[CategoryID], [t].[CategoryName]
FROM [Category] AS [t]
WHERE [t].[CategoryID] = 1
ORDER BY [t].[CategoryID]
SELECT [t.Products].[ProductID], [t.Products].[CategoryID], [t.Products].[ProductName], [t.Products].[UnitPrice]
FROM [Product] AS [t.Products]
INNER JOIN (
    SELECT TOP(1) [t0].[CategoryID]
    FROM [Category] AS [t0]
    WHERE [t0].[CategoryID] = 1
    ORDER BY [t0].[CategoryID]
) AS [t1] ON [t.Products].[CategoryID] = [t1].[CategoryID]
ORDER BY [t1].[CategoryID]
exec sp_executesql N'SET NOCOUNT ON;
INSERT INTO [Product] ([CategoryID], [ProductName], [UnitPrice])
VALUES (@p0, @p1, @p2);
SELECT [ProductID]
FROM [Product]
WHERE @@ROWCOUNT = 1 AND [ProductID] = scope_identity();

',N'@p0 int,@p1 nvarchar(4000),@p2 decimal(4,0)',@p0=1,@p1=N'VIVO',@p2=1500

2.3 更改关系

  如果更改实体的导航属性,则将对数据库中的外键列进行相应的更改。

using (var context = new LibingContext())
{
    var category = context.Categories.Find(2);
    var product = context.Products.Find(1);
    product.Category = category;

    context.SaveChanges();
}
exec sp_executesql N'SELECT TOP(1) [e].[CategoryID], [e].[CategoryName]
FROM [Category] AS [e]
WHERE [e].[CategoryID] = @__get_Item_0',N'@__get_Item_0 int',@__get_Item_0=2
exec sp_executesql N'SELECT TOP(1) [e].[ProductID], [e].[CategoryID], [e].[ProductName], [e].[UnitPrice]
FROM [Product] AS [e]
WHERE [e].[ProductID] = @__get_Item_0',N'@__get_Item_0 int',@__get_Item_0=1
exec sp_executesql N'SET NOCOUNT ON;
UPDATE [Product] SET [CategoryID] = @p0
WHERE [ProductID] = @p1;
SELECT @@ROWCOUNT;

',N'@p1 int,@p0 int',@p1=1,@p0=2

2.4 删除关系

  可以通过将引用导航设置为 null 或从集合导航中删除相关实体来删除关系。

  默认情况下,对于必选关系,将配置级联删除行为,并将从数据库中删除子实体/依赖实体。 对于可选关系,默认情况下不会配置级联删除,但会将外键属性设置为 null。

using (var context = new LibingContext())
{
    var category = context.Categories
        .Include(t => t.Products)
        .Where(t => t.CategoryID == 1)
        .FirstOrDefault();

    //category.Products.Remove(category.Products.FirstOrDefault());
    category.Products = null;

    context.SaveChanges();
}
SELECT TOP(1) [t].[CategoryID], [t].[CategoryName]
FROM [Category] AS [t]
WHERE [t].[CategoryID] = 1
ORDER BY [t].[CategoryID]
SELECT [t.Products].[ProductID], [t.Products].[CategoryID], [t.Products].[ProductName], [t.Products].[UnitPrice]
FROM [Product] AS [t.Products]
INNER JOIN (
    SELECT TOP(1) [t0].[CategoryID]
    FROM [Category] AS [t0]
    WHERE [t0].[CategoryID] = 1
    ORDER BY [t0].[CategoryID]
) AS [t1] ON [t.Products].[CategoryID] = [t1].[CategoryID]
ORDER BY [t1].[CategoryID]
exec sp_executesql N'SET NOCOUNT ON;
DELETE FROM [Product]
WHERE [ProductID] = @p0;
SELECT @@ROWCOUNT;

',N'@p0 int',@p0=2
exec sp_executesql N'SET NOCOUNT ON;
DELETE FROM [Product]
WHERE [ProductID] = @p0;
SELECT @@ROWCOUNT;

',N'@p0 int',@p0=3

3. 级联删除

相关文章:

  • ​Python 3 新特性:类型注解
  • 年会全记录 | Hi,菜鸟,五周岁生日快乐哇!
  • Swift 项目总结 06 基于控制器的全局状态栏管理
  • 织梦网站安装目录更换后,怎么更换上传网站中图片路径
  • 【Android Studio安装部署系列】二十四、Android studio中Gradle插件版本和Gradle版本关系...
  • 基于 HTML5 WebGL 的 3D 棉花加工监控系统
  • 16-client、offset、scroll系列
  • 数据结构之 二叉树
  • 【Touchinput 】指定输入方法类型(11)
  • iOS中父类readonly属性修改
  • μCOS-II系统之事件(event)的使用规则及MUTEX实例
  • 之所以一无所成,并不是我们不够努力
  • [转]Ubuntu16 压缩解压文件命令
  • 数组全部整理
  • corosync+pacemaker配置高可用集群(需要额外安装crm工具)
  • [LeetCode] Wiggle Sort
  • Android 控件背景颜色处理
  • Angular4 模板式表单用法以及验证
  • Node + FFmpeg 实现Canvas动画导出视频
  • Vim Clutch | 面向脚踏板编程……
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • 基于HAProxy的高性能缓存服务器nuster
  • 开发了一款写作软件(OSX,Windows),附带Electron开发指南
  • 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的?
  • 算法之不定期更新(一)(2018-04-12)
  • 我这样减少了26.5M Java内存!
  • 移动端唤起键盘时取消position:fixed定位
  • # 执行时间 统计mysql_一文说尽 MySQL 优化原理
  • #pragam once 和 #ifndef 预编译头
  • #中的引用型是什么意识_Java中四种引用有什么区别以及应用场景
  • $$$$GB2312-80区位编码表$$$$
  • $NOIp2018$劝退记
  • (03)光刻——半导体电路的绘制
  • (1)(1.13) SiK无线电高级配置(五)
  • (1/2)敏捷实践指南 Agile Practice Guide ([美] Project Management institute 著)
  • (C++17) std算法之执行策略 execution
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (react踩过的坑)antd 如何同时获取一个select 的value和 label值
  • (二)WCF的Binding模型
  • (接口封装)
  • (转载)Linux 多线程条件变量同步
  • .md即markdown文件的基本常用编写语法
  • .net MVC中使用angularJs刷新页面数据列表
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • .NET序列化 serializable,反序列化
  • [04] Android逐帧动画(一)
  • [Android]Android P(9) WIFI学习笔记 - 扫描 (1)
  • [android]-如何在向服务器发送request时附加已保存的cookie数据
  • [C++] new和delete
  • [C++]高精度 bign (重载运算符版本)
  • [Java][Liferay] File system in liferay
  • [NCTF 2022] web题解
  • [oeasy]python0004_游乐场_和python一起玩耍_python解释器_数学运算
  • [one_demo_11]二分查找法
  • [one_demo_8]十进制转二进制