前言

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

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中同样运行上述代码通过对比前后表中数据看看。

更新前

更新后

我们通过对比可看到,导航属性对应的表没有进行更新,不要问我为啥,在前面我也有讲过在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();

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

    [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; }
}

            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();

说了这么多在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指定更新导航属性了解一下?的更多相关文章

  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比较好[转] JAVA格物致知基础篇:你所不知道的返回码 深入了解EntityFramework Core 2.1延迟加载(Lazy Loading) EntityFramework 6.x和EntityFramework Core关系映射中导航属性必须是public? 藏在正则表达式里的陷阱 两道面试题,带你解析Java类加载机制

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

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

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

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

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

  7. 【ASP.NET Core】EF Core - “导航属性”

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

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

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

  9. C# 数据操作系列 - 7. EF Core 导航属性配置

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

随机推荐

  1. ASP.NET的版本?

    问题源于这么一本书: <ASP.NET 4 解密(卷1)>,这本书大约是六七年前买的了,根据其名字,它讲述的是ASP.NET 4,那么ASP.NET现在究竟是什么版本?与.NET Fram ...

  2. php原生代码实现explode函数功能

    在开始代码前要先介绍几个PHP函数: explode()   把字符串打散成数组 strpos()     返回字符串在另一个字符串第一次出现的位置(对大小写敏感) strstr()       查找 ...

  3. 49个Spring经典面试题总结,附带答案,赶紧收藏

    1. 一般问题 1.1. 不同版本的 Spring Framework 有哪些主要功能? Version Feature Spring 2.5 发布于 2007 年.这是第一个支持注解的版本. Spr ...

  4. javaScript设计模式--观察者模式(observer)

    观察者模式(observer):又被称为 发布-订阅者模式或者消息机制,定义了一种依赖关系,解决了主体对象与观察者之间功能耦合. 一.这样的需求 在实现自己的需求,而添加一些功能代码,但是又不想新添加 ...

  5. qml demo分析(rssnews-常见新闻布局)

    一.效果展示 今儿来分析一篇常见的ui布局,完全使用qml编写,ui交互效果友好,如图1所示,是一个常见的客户端新闻展示效果,左侧是一个列表,右侧是新闻详情. 图1 新闻效果图 二.源码分析 首先先来 ...

  6. BeetleX之HttpClusterApi应用详解

    之前的文章已经介绍过如何使用HttpClusterApi进行去中心化的HTTP集群服务访问,这一章主要详细讲述如何使用HttpClusterApi,主要包括如何定义节点,创建服务接口和使用接口描述不同 ...

  7. LindDotNetCore~授权中间件的介绍

    回到目录 LindDotNetCore中间件 大叔认识中间件就是主要对http请求进行拦截,然后添加具体个性化功能的逻辑,这种把请求切开,添加新逻辑的方式一般称为面向方面的逻辑AOP! 授权中间件 请 ...

  8. 【Python3爬虫】斗鱼弹幕爬虫

    在网上找到了一份斗鱼弹幕服务器第三方接入协议v1.6.2,有了第三方接口,做起来就容易多了. 一.协议分析 斗鱼后台协议头设计如下: 这里的消息长度是我们发送的数据部分的长度和头部的长度之和,两个消息 ...

  9. vue和mpvue

    一.mixins的理解     vue中提供了一种混合机制--mixins,用来更高效的实现组件内容的复用.最开始我一度认为这个和组件好像没啥区别..后来发现错了.下面我们来看看mixins和普通情况 ...

  10. 安装Phalcon报错:gcc: Internal error: Killed (program cc1)

    起因 安装Phalcon可以参考github上面的README.md 下面是我在阿里云ECS服务器上面执行命令的过程: # 安装依赖 sudo yum install php-devel pcre-d ...