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

  • 相关阅读:
    cocos2d-x学习笔记(贪吃蛇代码)
    jQuery中animate的height的自适应
    [Docker02]Docker_registry
    [Docker03] Deploy LNMP on Docker
    Python OS Module
    前端设计框架
    Ansible权威指南-读书笔记
    python+selenium之悠悠博客学习笔记
    jenkins入门
    sed
  • 原文地址:https://www.cnblogs.com/bdqczhl/p/9316282.html
Copyright © 2020-2023  润新知