linq to sql中的自动缓存(对象跟踪)
这篇东西应该至少一年前就写的,不过因为个人太懒,一直没记下来,今天补上.
linq to sql中,对于同一个DataContext上下文环境,根据表主键选择记录时(当然这里所指的“记录”会自动转成“对象”),如果该记录已经被select过,默认情况下会被自动缓存下来,下次再选择时,将自动返回已缓存的对象,而不是重新从数据库里查询。
在很多情况下(特别是查询的场景),这会提高性能(因为避免了数据库重复查询),但是也时候也会带来麻烦:
比如我们取出一个对象后,对其属性做了修改,然后提交到数据库前,想比较一下原始记录,如果某些属性修改过了,则这样处理,如果未被修改过,则那样处理。因为缓存的关系,我们重新取出原始记录时,其实取出的并不是数据库中的原始值,而缓存在内存里的对象实例(即修改后的对象 ),所以比较时,永远都会返回未修改过。
测试原始记录如下:
测试代码如下:
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、关闭默认的对象跟踪
即:
dbDataContext db = new dbDataContext();
db.ObjectTrackingEnabled = false;//关闭默认的对象跟踪
这个办法最简单,但却是一刀切的办法,会关闭db所有的缓存功能,在查询请求远大于更新请求的场景下,个人并不太喜欢。
2、创建一个新的DataContext上下文来查询原始值
即:把u2的取值部分改为
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中还是用传统的连接串方式建立DbContext更好些
首先,在LINQTOSQL中可以这样建立一个dbcontext private TEntity GetOriginal(TEntity entity) { ...
- 在Linq to Sql中管理并发更新时的冲突(3):使用记录的时间戳进行检测
我们描述了Linq to Sql检测在更新时是否产生了冲突的基本方法:将该记录每个字段原来的值和更新时的值进行对比,如果稍有不同则意味着记录被修改过,因此产生了更新冲突.不过您是否有这样的感觉,这种方 ...
- 在LINQ to SQL中使用Translate方法以及修改查询用SQL
目前LINQ to SQL的资料不多--老赵的意思是,目前能找到的资料都难以摆脱"官方用法"的"阴影".LINQ to SQL最权威的资料自然是MSDN,但是M ...
- 浅谈Linq to SQL中的模式
学习Linq to SQL也有一段时间了,感叹它做为ORM虽然简单但是功能效率都还不错,从编译器和语言层面支持上来看,它是其他ORM工具不能比的.Linq to SQL中运用了很多模式对自身的效率进行 ...
- 【转】 LINQ TO SQL中的selectMany
首先看SelectMany的定义: Queryable中的SelectMany 方法:将序列的每个元素投影到一个 IEnumerable<(Of <(T>)>) 并将结果序列组 ...
- java用redis缓存的步骤_详解在Java程序中运用Redis缓存对象的方法|chu
这段时间一直有人问如何在Redis中缓存Java中的List 集合数据,其实很简单,常用的方式有两种: 1. 利用序列化,把对象序列化成二进制格式,Redis 提供了 相关API方法存储二进制,取数据 ...
- 如何在SQL中设置自动编号
如何在SQL中设置自动编号 关键词: 自动编号 SQL 设置 Nicholas 课程设计 你创建一个表,把其中一个列(比如"ID")的"标识列&q ...
- Linq To Sql中实现Left Join与Inner Join使用Linq语法与lambda表达式
当前有两个表,sgroup与sgroupuser,两者通过gKey关联,而sgroup表记录的是组,而sgroupuser记录是组中的用户,因此在sgroupuser中不一定有数据.需要使用Left ...
- linq to sql 中,如何解决多条件查询问题,答案,用表达式树! (下)
,我们做了基于linq to sql 的多条件组合查询,但通过监视数据库发现,这样做的成本比较高,每次都要取出全部的数据到内存进行筛选.如何从真正意义上做到延迟加载,即一次只从数据库中取我们需要的用到 ...
最新文章
- MongoDB探索之路(二)——系统设计之CRUD
- select2的一些特性效果
- java 27 - 4 反射之 通过反射获取成员变量并使用
- 框架开发之Java注解的妙用
- 深入理解ROS技术 【3】ROS下的模块详解(129-180)
- spring cloud 定时任务
- 信息竞赛进阶指南--搜索相关(模板)
- java 拷贝属性值_Java 反射拷贝相同的属性值到指定对象中(两种实现方式)
- Oracle中用于发送邮件的存储过程
- 移动端日期控件 mobiscroll
- 每日英语:6 Brainy Habits of the Wisest People
- 【渝粤教育】电大中专药物化学基础作业 题库
- VS2013 + Qt 提示 There‘s no Qt version assigned to this project for platform Win32
- C盘爆红,一个操作将微信缓存踢走
- GPU求解粘性不可压流体
- MPC与LQR的详细对比分析
- [NOIP2017模拟]permut
- Android Studio 制作APP启动界面(Splash)
- 计算机一级经验分享,计算机一级考试经验
- 萧伯纳学演讲不怕出丑