linq to sql中的自动缓存(对象跟踪)
linq to sql中,对于同一个DataContext上下文环境,根据表主键选择记录时(当然这里所指的“记录”会自动转成“对象”),如果该记录已经被select过,默认情况下会被自动缓存下来,下次再选择时,将自动返回已缓存的对象,而不是重新从数据库里查询。
在很多情况下(特别是查询的场景),这会提高性能(因为避免了数据库重复查询),但是也时候也会带来麻烦:
比如我们取出一个对象后,对其属性做了修改,然后提交到数据库前,想比较一下原始记录,如果某些属性修改过了,则这样处理,如果未被修改过,则那样处理。因为缓存的关系,我们重新取出原始记录时,其实取出的并不是数据库中的原始值,而缓存在内存里的对象实例(即修改后的对象 ),所以比较时,永远都会返回未修改过。
测试原始记录如下:

测试代码如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
using System;using System.Linq;using System.Diagnostics;namespace webApp{ public partial class Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { dbDataContext db = new dbDataContext(); var u1 = db.Users.FirstOrDefault(c=>c.Id==1); u1.Photo = "new value";//这里修改了用户的头象 var u2 = db.Users.FirstOrDefault(c => c.Id == u1.Id);//重新查询原始值 if (u2.Photo == u1.Photo) { Debug.WriteLine("用户头象未被修改!"); } else { Debug.WriteLine("用户头象被修改过了!"); //to do list... //如果保存到数据库,还应该删除原来的旧头象 } } }} |
如果运行一下,将永远得到的都是"用户头象未被修改!"。
解决办法有二个:
1、关闭默认的对象跟踪
即:
|
1
2
|
dbDataContext db = new dbDataContext();db.ObjectTrackingEnabled = false;//关闭默认的对象跟踪 |
这个办法最简单,但却是一刀切的办法,会关闭db所有的缓存功能,在查询请求远大于更新请求的场景下,个人并不太喜欢。
2、创建一个新的DataContext上下文来查询原始值
即:把u2的取值部分改为
|
1
2
3
4
5
6
|
User u2 = null;using (dbDataContext db2 = new dbDataContext()) //创建一个新的上下文{ u2 = db2.Users.FirstOrDefault(c => c.Id == u1.Id);//重新查询原始值 } |
临时创建一个db2,然后用它来重新查询原始值,由于db2是刚创建,之前肯定没有查询过Id==u1.id的记录,所以缓存是空的,因此会到数据库重新查询,当然db2用完后,会自动释放相关资源(using的功劳!)
linq to sql中的自动缓存(对象跟踪)的更多相关文章
- LINQ TO SQL 中的join(转帖)
http://www.cnblogs.com/ASPNET2008/archive/2008/12/21/1358152.html join对于喜欢写SQL的朋友来说还是比较实用,也比较容易接受的东西 ...
- Linq to sql中继承类映射转换问题
类型为的数据成员“Int32 VTOUID”不是类型的映射的一部分.该成员是否位于继承层次结构根节点的上方? 想躲开Linq to sql中问题限制可真是不容易: http://www.makaido ...
- LINQ to SQL 中 Concat、Union、Intersect、Except 方法的使用
Ø 前言 LINQ to SQL 中需要对两个或多个数据集进行操作,比如:合并.取交集等,主要使用下面四个方法,这四个方法都是 System.Linq.IQueryable<out T> ...
- Linq to sql中使用DateDiff()
Linq to sql中使用DateDiff() 计算时间差的方法 第一种办法: from p in PurchaseLists where EntityFunctions.DiffDays(p.Cr ...
- Linq To Sql中实现Left Join与Inner Join使用Linq语法与lambda表达式
当前有两个表,sgroup与sgroupuser,两者通过gKey关联,而sgroup表记录的是组,而sgroupuser记录是组中的用户,因此在sgroupuser中不一定有数据.需要使用Left ...
- EFCore扩展:IQueryable(linq)或sql执行的查询缓存与清理
前言 上一篇讲述了执行sql和配置的一些功能,这篇说明IQueryable(linq)或执行sql的查询缓存与清理,包括扩展到将缓存存储到Redis中. 扩展类库源码: github:https:// ...
- 关于Linq to Sql 中的left join 中defaultifempty的相关注意事项
在使用Linq to Sql的时候,进行两个表的左连接的时候要注意defaultifempty的使用,这个函数本来的意思即是:如果为空则使用默认值代替,默认值为 NULL ,当然也可以使用defaul ...
- wcf+linq to sql中关联查询返回数据问题
前段时间准备采用wcf+nh框架开发sl程序,发现采用nh开发不适合我的中型.并且快速开发项目,所以综合考量了下,决定采用wcf+linq to sql . 但是此模式也有缺点,也是linq to s ...
- linq to sql 中增删改查
首先我先说一下,如果真的要用linq做项目的话,也会是比较方便的.已经尝试了在三层架构中应用linq to sql 比较方便. //有三个不同的数据库表,所以写法不一样 public class Li ...
随机推荐
- HTML5新特性postMessage解决跨域
window.postMessage的功能是允许程序员跨域在两个窗口/frames间发送数据信息.基本上,它就像是跨域的AJAX,但不是浏览器跟服务器之间交互,而是在两个客户端之间通信.让我们来看一下 ...
- C#演化过程--各个版本新增加特性
- vagrant特性——基于docker开发环境(docker和vagrant的结合)-1-基本使用
Docker vagrant提供了使用Docker作为provider(其他的provider有virtualBox.VMware\hyper-V等)的开箱即用支持.这允许你的开发环境由Docker容 ...
- Python2.7-getpass
getpass模块,当用户输入密码时,可以不在屏幕上显示,但是用户也不能看到自己输了几位输了什么 1.模块方法 1.1 getpass.getpass([prompt[, stream]]):prom ...
- java过滤器filter使用
一:filter:过滤器,拦截servlet的请求和响应. 1. package jd.com.filter; import javax.servlet.*; import java.io.IOExc ...
- python3——print使用
print的初步认识:对于科班出身的或有相关经验的人来说,学习python是相当有趣的事,因为可以做日常任务, 比如自动备份你的MP3:可以做网站,如YouTube就是Python写的:可以做 ...
- Java中的单利模式介绍
单利模式:本来是不准备写的,但是最近发现好多公司面试时都会或多或少的提到单利模式,因此今天把单利模式拉出来说说. 定义:只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且 ...
- Jmeter—控件
Jmeter有许多控件,可以在我们模拟测试请求时使用. Jmeter共有这8类控件: 配置元件—Http请求默认值 作用:仅设置一次目标URL服务器地址,之后不需要每次请求都写完整的,仅写相对地址就可 ...
- iOS VideoToolBox decoder解码失败(-12909和-12911)问题解决
对于任何H.264解码器而言,都要将SPS和PPS信息传递给解码器.FFmpeg内部做了设置,所以没有显示设置.但是对于硬件解码器来讲,开发者必须手动设置.另外,使用FFmpeg解码出来的视频帧是以Y ...
- jupyter notebook的两个使用技巧
1.设置jupyter notebook的密码: Jupyter-notebook password 2.查看jupyter notebook的token: Jupyter notebook list