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的功劳!) 

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小狼的世界

Curl操作Elasticsearch的常用方法

Elasticsearch对于文档操作,提供了以下几种API,本文就说明如何使用curl方式来调用这些API。

1532
来自专栏zingpLiu

Django快速入门

Django 是用 Python 写的一个自由和开放源码 web 应用程序框架。 web框架是一套组件,能帮助你更快、更容易地开发web站点。当你开始构建一个w...

1153
来自专栏GreenLeaves

WCF系列教程之WCF服务宿主与WCF服务部署

本文参考自http://www.cnblogs.com/wangweimutou/p/4377062.html,纯属读书笔记,加深记忆。 一、简介 任何一个程序...

2348
来自专栏张首富-小白的成长历程

redis缓存服务器

#你当前没有指定配置文件,以默认的配置文件启动,如果你想指定配置文件你可以redis-server 文件所在位置

5062
来自专栏Golang

influxdb 简介与实现(一)

InfluxDB是一个开源的没有外部依赖的时间序列数据库。适用于记录度量,事件及执行分析。

2614
来自专栏晓晨的专栏

IdentityServer Topics(5)- 使用第三方登录

1323
来自专栏Esofar 开发日记

[译]RabbitMQ教程C#版 - 远程过程调用(RPC)

但是如果我们想要运行一个在远程计算机上的函数并等待其结果呢?这将是另外一回事了。这种模式通常被称为 远程过程调用 或 RPC 。

1092
来自专栏散尽浮华

针对Nginx日志的相关运维操作记录

在分析服务器运行情况和业务数据时,nginx日志是非常可靠的数据来源,而掌握常用的nginx日志分析命令的应用技巧则有着事半功倍的作用,可以快速进行定位和统计。...

50710
来自专栏熊二哥

.NET工作准备--04ASP.NET

(已过时) ASP.NET 1.开发基础 *asp.net以什么形式运行?.net宿主的概念,ISAPI的概念,ASP.NET基本运行机制; .net宿主...

2415
来自专栏熊训德的专栏

Hbase replication源码分析

本文主要通过Replication的核心原理和failover 过程,对Hbase replication源码分析,希望对大家了解Hbase源码有所帮助。

1.3K0

扫码关注云+社区

领取腾讯云代金券