EntityFramework Core指定更新导航属性了解一下?

时间:2022-08-27 15:02:38

前言

本文来自和何镇汐大哥的探讨,很多时候我习惯于和别人交流过后会思考一些问题,无论是天马行空还是浅薄的想法都会记录下来,或许看到此博文的您能给我更多的思考,与人交流总能收获很多东西,出发点不一样则结论 不一样,思维方式不一样则路径不一样,愿你我共同进步。

EntityFramework Core无跟踪视图

首先依然给出本文需要用到的两个实体,如下:

    public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public DateTime CreatedTime { get; set; }
public DateTime ModifiedTime { get; set; }
public byte Status { get; set; }
public bool IsDeleted { get; set; }
public ICollection<Post> Posts { get; set; } = new List<Post>();
}
    public class Post
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime CreatedTime { get; set; }
public DateTime ModifiedTime { get; set; } public int BlogId { get; set; }
public Blog Blog { get; set; } }

在EF Core中给我们提供了Update和UpdateRange方法,这两个方法你说作用大吧,我看作用也没有那么大。要利用这两个方法,必须对值进行一一赋值,如下:

            var dbContext = new EFCoreDbContext();
var dbBlog = dbContext.Blogs.Include(d => d.Posts).FirstOrDefault(d => d.Id == );
dbBlog.Name = "Jeffcky";
foreach (var post in dbBlog.Posts)
{
post.Name = "《你必须掌握的EntityFramework 6.x与Core 2.0》";
}
dbContext.Update(dbBlog);
dbContext.SaveChanges();

在EF 6.x中缺失Update和UpdateRange方法,但是它可以进行如下更新啊不是。

            var dbContext = new EFCoreDbContext();
var newBlog = new Blog()
{
Id = ,
Name = "Jeffcky1",
IsDeleted = false,
Status = ,
Url = "https://www.cnblogs.com/CreateMyself",
CreatedTime = DateTime.Now,
ModifiedTime = DateTime.Now,
Posts = new List<Post>()
{
new Post()
{
Id = ,
BlogId = ,
Name = "EF Core TrackGraph",
CreatedTime = DateTime.Now,
ModifiedTime = DateTime.Now
}
}
}; var dbBlog = dbContext.Blogs.Include(d => d.Posts).FirstOrDefault(d => d.Id == );
dbContext.Entry(dbBlog).CurrentValues.SetValues(newBlog);
dbContext.SaveChanges();

不太了解详情的童鞋可能就说了在EF Core中也可以利用上述CurrentValues来指定更新列啊,如果您这样想那就大错特错了,来我们在EF Core中同样运行上述代码通过对比前后表中数据看看。

更新前

EntityFramework Core指定更新导航属性了解一下?

EntityFramework Core指定更新导航属性了解一下?

更新后

EntityFramework Core指定更新导航属性了解一下?

EntityFramework Core指定更新导航属性了解一下?

我们通过对比可看到,导航属性对应的表没有进行更新,不要问我为啥,在前面我也有讲过在EF Core中这种情况类似于和添加一样通过手动这是状态为Added,在EF 6.x中只要更新主表则对应与之相关的导航属性也会更新,但是在EF Core中只会更新主表,EF 6.x这么好的指定更新反而被剔除了,实在不应该啊。有人说赋值两次啊,不好意思也不行,如下:

            var dbContext = new EFCoreDbContext();
var newBlog = new Blog()
{
Id = ,
Name = "Jeffcky1",
IsDeleted = false,
Status = ,
Url = "https://www.cnblogs.com/CreateMyself",
CreatedTime = DateTime.Now,
ModifiedTime = DateTime.Now,
Posts = new List<Post>()
{
new Post()
{
Id = ,
BlogId = ,
Name = "EF Core TrackGraph",
CreatedTime = DateTime.Now,
ModifiedTime = DateTime.Now
}
}
}; var dbBlog = dbContext.Blogs.Include(d => d.Posts).FirstOrDefault(d => d.Id == );
dbContext.Entry(dbBlog).CurrentValues.SetValues(newBlog);
dbContext.Entry(dbBlog.Posts).CurrentValues.SetValues(newBlog.Posts);
dbContext.SaveChanges();

EntityFramework Core指定更新导航属性了解一下?

上述这种方式对关系映射是不行的,但是若是复杂属性则是可以,如下:

    [Owned]
public class StreetAddress
{
public string Street { get; set; }
public string City { get; set; }
} public class Order
{
public int Id { get; set; }
public StreetAddress ShippingAddress { get; set; }
}

EntityFramework Core指定更新导航属性了解一下?

            var dbContext = new EFCoreDbContext();
var order = dbContext.Orders.FirstOrDefault();
order.ShippingAddress.City = "city";
order.ShippingAddress.Street = "street";
dbContext.SaveChanges();

这样更新肯定是可以的,我们不做过多探讨,利用CurrentValues只能进行两次赋值才行,如下。

            var newOrder = new Order()
{
Id = ,
ShippingAddress = new StreetAddress()
{
City = "city",
Street = "street"
}
};
var dbContext = new EFCoreDbContext();
var order = dbContext.Orders.FirstOrDefault();
dbContext.Entry(order).CurrentValues.SetValues(newOrder);
dbContext.Entry(order.ShippingAddress).CurrentValues.SetValues(newOrder.ShippingAddress);
var result = dbContext.SaveChanges();

让我们再次回到更新Blog,除了利用CurrentValues指定更新外,我们还可以在查询Posts时不进行显式加载,然后调用直接将更新newBlog赋值与dbBlog,这种方式和手动赋值本质一样,但是至少不用一一赋值不是,如下:

            var dbContext = new EFCoreDbContext();
var newBlog = new Blog()
{
Id = ,
Name = "Jeffcky1",
IsDeleted = false,
Status = ,
Url = "https://www.cnblogs.com/CreateMyself",
CreatedTime = DateTime.Now,
ModifiedTime = DateTime.Now,
Posts = new List<Post>()
{
new Post()
{
Id = ,
BlogId = ,
Name = "EF Core TrackGraph",
CreatedTime = DateTime.Now,
ModifiedTime = DateTime.Now
}
}
}; var dbBlog = dbContext.Blogs
.AsNoTracking()
.Include(d => d.Posts).FirstOrDefault(d => d.Id == );
dbBlog = newBlog;
dbContext.Update(dbBlog);
var result = dbContext.SaveChanges();

EntityFramework Core指定更新导航属性了解一下?

说了这么多在EF Core中对于指定更新列不是太友好,当属性过多利用手动赋值就太麻烦,应该保留EF 6.x中利用CurrntValues对导航属性也进行直接更新岂不更好,如果调用Update方法将当前实体与快照中的实体比较指定更新列应该才是最佳方案。

Include....ThenInclude加载导航属性是否为最佳方案呢?

我们看如下三个示例实体

    public class A
{
public int Id { get; set; }
public ICollection<B> Bs { get; set; }
} public class B
{
public int Id { get; set; }
public C C { get; set; }
} public class C
{
public int Id { get; set; }
}

此时我们来查询A并通过显式加载B和C,如下:

            var dbContext = new EFCoreDbContext();
var As = dbContext.As.Include(d => d.Bs).ThenInclude(d => d.C).ToList();

大部分查询我们都会进行如上查询,但是我们是否思考是上述是否为最佳方案呢?或者性能更好呢?我也不知道,我也只是纯属猜测,因为要是我们进行如下加载数据呢?

        static void IncludeLoadCollection(EFCoreDbContext dbContext, object obj)
{
var entityEntry = dbContext.Entry(obj);
foreach (var collection in entityEntry.Collections)
{
if (collection.IsLoaded)
{
continue;
} collection.Load(); if (collection.CurrentValue != null)
{
foreach (var child in collection.CurrentValue)
{
IncludeLoadCollection(dbContext, child);
}
}
}
}
           var dbContext = new EFCoreDbContext();

            var a = dbContext.As.FirstOrDefault();
IncludeLoadCollection(dbContext, a);

如上代码未经测试,只是作为个人思考而给,您看到后私下可自行测试对比上述方案和通过Include....ThenInclude哪种方案更好呢?本文稍微讲解了下个人认为EF Core对于指定更新没有一个恰当的方式除了手动更新列外,当然字段太多,大部分情况下都会借助AutoMapper等进行DTO。

出版购买通知

现京东和淘宝上可正式预售购买《你必须掌握的EntityFramework 6.x与Core 2.0》书籍,我博客右上方也给了一个购买链接,让各位久等了。感谢各位同行一直以来的大力支持,同时也再次感谢博客园这个大平台,给了我机会去分享技术,我对EF既谈不上精通更谈不上不专家只不过是平时私下喜欢研究罢了,书中大部分都是我个人的理解,同时技术更新迭代太快,我也一直在追逐中而非停滞不前,我相信:无论出身环境怎样,自身天赋如何,笃定都可以通过自身的努力来改变并且成长。

EntityFramework Core指定更新导航属性了解一下?

EntityFramework Core指定更新导航属性了解一下?的更多相关文章

  1. 关于Entity Framework自动关联查询与自动关联更新导航属性对应的实体注意事项说明

    一.首先了解下Entity Framework 自动关联查询: Entity Framework 自动关联查询,有三种方法:Lazy Loading(延迟加载),Eager Loading(预先加载) ...

  2. ef 更新导航属性

    总之,要让所有的东西,都被DbContext管理状态 1.查出来,改了,再提交 2.new 出来,attach,再改,再提交 以上两种都较好理解 3.new出来,改了,再attach,在改状态,再提交 ...

  3. EntityFramework Core 3多次Include导致查询性能低之解决方案

    前言 上述我们简单讲解了几个小问题,这节我们再来看看如标题EF Core中多次Include导致出现性能的问题,废话少说,直接开门见山. EntityFramework Core 3多次Include ...

  4. 你所不知道的库存超限做法 服务器一般达到多少qps比较好&lbrack;转&rsqb; JAVA格物致知基础篇:你所不知道的返回码 深入了解EntityFramework Core 2&period;1延迟加载(Lazy Loading) EntityFramework 6&period;x和EntityFramework Core关系映射中导航属性必须是public? 藏在正则表达式里的陷阱 两道面试题,带你解析Java类加载机制

    你所不知道的库存超限做法 在互联网企业中,限购的做法,多种多样,有的别出心裁,有的因循守旧,但是种种做法皆想达到的目的,无外乎几种,商品卖的完,系统抗的住,库存不超限.虽然短短数语,却有着说不完,道不 ...

  5. EntityFramework Core饥饿加载忽略导航属性问题

    前言 .NET Core项目利用EntityFramework Core作为数据访问层一直在进行中,一直没有过多的去关注背后生成的SQL语句,然后老大捞出日志文件一看,恩,有问题了,所以本文产生了,也 ...

  6. EntityFramework 6&period;x和EntityFramework Core关系映射中导航属性必须是public?

    前言 不知我们是否思考过一个问题,在关系映射中对于导航属性的访问修饰符是否一定必须为public呢?如果从未想过这个问题,那么我们接下来来探讨这个问题. EF 6.x和EF Core 何种情况下必须配 ...

  7. 【ASP&period;NET Core】EF Core - &OpenCurlyDoubleQuote;导航属性”

    “导航属性”是实体框架用得算是比较频繁的概念. 首先,它是类型成员,其次,他是属性,这不是 F 话,而是明确它的本质.那么,什么场景下会用到导航属性呢?重点就落在“导航”一词上了,当实体 A 需要引用 ...

  8. EF Core反向导航属性解决多对一关系

    多对一是一种很常见的关系,例如:一个班级有一个学生集合属性,同时,班级有班长.语文课代表.数学课代表等单个学生属性,如果定义2个实体类,班级SchoolClass和学生Student,那么,班级Sch ...

  9. C&num; 数据操作系列 - 7&period; EF Core 导航属性配置

    在上一篇,大概介绍了Entity Framework Core关于关系映射的逻辑.在上一篇中留下了EF的外键映射没有说,也就是一对一,一对多,多对一,多对多的关系等.这一篇将为大家细细分析一下,如何设 ...

随机推荐

  1. 剑指Offer面试题:16&period;合并两个排序的链表

    PS:这也是一道出镜率极高的面试题,我相信很多童鞋都会很眼熟,就像于千万人之中遇见不期而遇的人,没有别的话可说,唯有轻轻地问一声:“哦,原来你也在这里? ” 一.题目:合并两个排序的链表 题目:输入两 ...

  2. swagger for c&num; webapi

    最近迷上了前后端分离的开发架构,工作中的项目几乎都采取这种模式,自己主要担任服务端RestFul风格的Webapi开发.那么问题来了,当前端开发人员找我要api说明文档的时候,曾一度非常可耻的冒出过w ...

  3. C&num;中导入Win32 API函数

    C#中导入Win32 API的方法: 1.引用命名空间 using System.Net.Security; using System.Runtime.InteropServices; 2. [Dll ...

  4. SQL 查询学生缺考情况

    有三个表,如果学生缺考,那么在成绩表中就不存在这个学生的这门课程成绩的记录,写一段SQL语句,检索出每个学生缺考的科目.A 学生表(student)字段1 学生号(s_id)字段2 学生名(s_nam ...

  5. mac下U盘装机系统的制作(命令行)

    1,不插入U盘和插入U盘分别命令检测硬盘,确定要制作的U盘号:diskutil list 2,卸载usb盘,不推出,diskutil umountDisk /dev/disk1 3,将dmg写入U盘, ...

  6. JavaWeb学习记录(二十六)——在线人数统计HttpSessionListener监听实现

    一.session销毁控制层代码 public class InvalidateSession extends HttpServlet { public void doGet(HttpServletR ...

  7. HTML5 文件域&plus;FileReader 读取文件&lpar;二&rpar;

    一.读取文本文件内容,指定字符编码 <div class="container"> <!--文本文件验证--> <input type="f ...

  8. (转载)mysql中百万级数据插入速度测试

    (转载)http://www.111cn.net/database/mysql/42453.htm 100W的数据对于很多朋友来说算小菜了,但今天我就想到创建一个大量数据的测试环境,于是找了一下怎么插 ...

  9. linux查询当前进程数的命令

    $command = "ps aux | grep  'zb_insure/get_order_info_from_queue.php' | grep -v 'grep' |  grep - ...

  10. Android 动画深入分析

    一些娱乐动画安德鲁斯被广泛使用应用上述的.在不牺牲性能,它可以带来非常好的体验,下面会解释具体的实现安卓动画.知识的学校一个明确清晰的白色. 动画类型 Android的animation由四种类型组成 ...