东莞网站建设公司百推,wordpress版本怎么升级,自己做的网站页面错误,网站群建设方案前言最近将RabbitMQ正式封装引入到.NET Core 2.0项目当中#xff0c;之前从未接触过这个高大上的东东跟着老大学习中#xff0c;其中收获不少#xff0c;本打算再看看RabbitMQ有时间写写#xff0c;回来后和何镇汐大哥探讨了一点关于EF和EF Core的内容#xff0c;于是乎本… 前言最近将RabbitMQ正式封装引入到.NET Core 2.0项目当中之前从未接触过这个高大上的东东跟着老大学习中其中收获不少本打算再看看RabbitMQ有时间写写回来后和何镇汐大哥探讨了一点关于EF和EF Core的内容于是乎本文就出来了。EF 6.x和EF Core中的查询缓存想必大家都有耳闻或者了解从数据库中查询出来的实体会形成快照在内存中Copy一份且被上下文跟踪接下来我们要讲的内容就是这个我们来看看。EF 6.x和EF Core查询缓存思考首先我利用EF Core通过一个例子来进入今天的主题在此过程中您也可多一点思考空间并对照和您想象中的结果是否有出入或者不一致的地方。var context new EFCoreDbContext(); var blog1 context.Blogs.Find(3); Console.WriteLine($数据库原始值为{blog1.Name}); blog1.Name Jeffcky; var blog2 context.Blogs.FirstOrDefault(d d.Id 3); Console.WriteLine($查询数据库后的值为{blog2.Name}上述我们通过Find方法查询出Blog1然后对Name进行赋值紧接着我们再次查询主键等于3的实体您猜想一下blog2中的Name会等于多少呢我们看看如上图所示结果为Jeffcky有的童鞋就问了我们进行第一次查询时值为3然后我们仅仅只是赋值为Jeffcky并未提交当我们再次查询相同实体时结果却为Jeffcky呢难道不应该是3么对吧。稍微对EF或者EF Core有所了解的大佬们明白第一次查询时会有快照当下次查询时EF或者EF Core会在内存中根据第一次查询所对应的哈希值和主键去查找此时查找到则直接利用内存中的对象所以此时blog2的Name为Jeffcky。问题是不是到此就结束了呢如果是这样那我大半夜还浪费这时间写这篇博客接下来我们再来看看两次查询所生成的SQL如何在EF 6.x和EF Core中 通过Find方法基于主键查询查询可重用什么意思呢如上第一个查询采用参数化查询也就说如果我们下次再利用Find方法查询那么将不会到数据库查询而是直接从内存中返回有的童鞋就想了恩挺好这样显著提高了查询性能我只能说不一定看对应场景如果对于非常频繁的查询我个人觉得不建议用此方法因为还有对实体的更新操作啊此时数据更新了却在内存中的值没有更新显示到UI上也就是说是过期了值那么您觉得这个时候用Find方法还可取吗。对于第二个查询则直接采取赋值的形式在我即将出版的《你必须掌握的EntityFramework 6.x和Core 2.0》书中有讲解EF 6.x查询的很大问题这都不是事问题是第二次我们利用FirstOrDefault方法查询此时居然走数据库了不信您可以看看如下利用SQL Profiler监控得到的SQL语句。这就让人有点费解了第二个查询既然是到数据库中查询那为何我们得到的值当前第一次查询出来修改但未被提交的值呢这不是自相矛盾么EF Core这样设计的意义何在我也想不通我能想到的是在同一上下文中大部分情况下不会对同一实体查询多次但是谁能保证呢。 在EF Core中除了Find会进行翻译缓存其他比如First、FirstOrDefault、Last、LastOrDefault都会到数据库中查询当我们利用Last或者LastOrDefault查询时会出现更有意思的事情我们看看生成的SQL语句var blog3 context.Blogs.Last();EF Core大哥哥们这么简单的查询问题都没测试到么你翻译给我让我误以为这是返回所有列表了结果一看查询出来的值却是对的我想这是EF Core大哥哥们忘记加上TOP 1和ORDER BY了到github上一搜索原来有大神提过这个ISSUEhttps://github.com/aspnet/EntityFrameworkCore/issues/10493在2.1版本发布会解决这个问题。好了我们回到主题所遇到的问题在同一上下文查询同一实体第一次查询如果我们利用Find方法查询会进行翻译缓存待下一次再次查询时不会到数据库中查询如果是下一次查询不是利用Find方法查询比如FirstOrDefault此时会到数据库中查询但是此时的值却不是数据库中的值而是当前被修改而未被提交的值那么我们如何获取数据库中的值而不是当前修改而未被提交的值呢请往下看。EF和EF Core获取数据库值而不是当前修改未被提交的值我们讨论了问题的出现接下来我们尝试利用方法来解决我们可以对上下文所跟踪的实体进行移除通过Local.Remove如下var context new EFCoreDbContext(); var blog1 context.Blogs.Find(3); Console.WriteLine($数据库原始值为{blog1.Name}); blog1.Name Jeffcky; context.Blogs.Local.Remove(blog1); var blog2 context.Blogs.FirstOrDefault(d d.Id 3); Console.WriteLine($查询数据库后的值为{blog2.Name});Local方法意味获取在本地所添加、修改等的实体我们获取被上下文所本地被上下文所跟踪的实体然后移除继而再进行查询是不是就可以移除呢不好意思移除不了。利用AsNoTracking方法这个算是最简单的方法之一了仅仅对于查询而言通过此方法不会形成快照从而提高查询性能。var context new EFCoreDbContext(); var blog1 context.Blogs.Find(3); Console.WriteLine($数据库原始值为{blog1.Name}); blog1.Name Jeffcky; var blog2 context.Blogs.AsNoTracking().FirstOrDefault(d d.Id 3); Console.WriteLine($查询数据库后的值为{blog2.Name});将实体状态标记为Detached不被上下文跟踪var context new EFCoreDbContext(); var blog1 context.Blogs.Find(3); Console.WriteLine($数据库原始值为{blog1.Name}); blog1.Name Jeffcky; context.Entry(blog1).State EntityState.Detached; var blog2 context.Blogs.FirstOrDefault(d d.Id 3); Console.WriteLine($查询数据库后的值为{blog2.Name}); 通过Reload方法刷新实体var context new EFCoreDbContext(); var blog1 context.Blogs.Find(3); Console.WriteLine($数据库原始值为{blog1.Name}); blog1.Name Jeffcky; context.Entry(blog1).Reload(); var blog2 context.Blogs.FirstOrDefault(d d.Id 3); Console.WriteLine($查询数据库后的值为{blog2.Name});通过GetDatabaseValues方法直接获取数据库中值var context new EFCoreDbContext(); var blog1 context.Blogs.Find(3); Console.WriteLine($数据库原始值为{blog1.Name}); blog1.Name Jeffcky; var blog2 (Blog)context.Entry(blog1).GetDatabaseValues().ToObject(); Console.WriteLine(blog2.Name); //或者 var db context.Entry(blog1).GetDatabaseValues(); Console.WriteLine(db[Name]);总结好了今天的内容就到此为止了无论是EF 6.x还是EF Core只要我们对一些原理足够了解才不至于出现让人意想不到的问题。希望本文对您有所帮助下节开始讲讲RabbitMQ我们下节再会。原文地址https://www.cnblogs.com/CreateMyself/p/8965216.html.NET社区新闻深度好文欢迎访问公众号文章汇总 http://www.csharpkit.com