.Net cache与cache更新

主要用到 system.runtime.caching

框架自动给了一个默认值 memorycache.default;

查看微软关于memorycache的介绍,可以看到它有add、get、set 、 contains 、remove等几个方法, 也就是我们常用的了,比较简单

网上找了一段对这个封装的代码:

/// <summary>
    /// represents a memorycachecache
    /// </summary>
    public static class cachemanager
    {
        public static objectcache cache
        {
            get
            {
                return memorycache.default;
            }
        }

        public static bool contains(string key)
        {
            return cache.contains(key);
        }

        /// <summary>
        /// gets or sets the value associated with the specified key.
        /// </summary>
        /// <typeparam name="t">type</typeparam>
        /// <param name="key">the key of the value to get.</param>
        /// <returns>the value associated with the specified key.</returns>
        public static t get<t>(string key)
        {
            return (t)cache[key];
        }

        /// <summary>
        /// adds the specified key and object to the cache.
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="data">data</param>
        /// <param name="cachetime">cache time</param>
        public static void set(string key, object data, int cachetime)
        {
            if (data == null)
                return;

            var policy = new cacheitempolicy();
            policy.absoluteexpiration = datetime.now + timespan.fromminutes(cachetime);
            cache.set(new cacheitem(key, data), policy);
        }/// <summary>
        /// gets a value indicating whether the value associated with the specified key is cached
        /// </summary>
        /// <param name="key">key</param>
        /// <returns>result</returns>
        public static bool isset(string key)
        {
            return (cache.contains(key));
        }

        /// <summary>
        /// removes the value with the specified key from the cache
        /// </summary>
        /// <param name="key">/key</param>
        public static void remove(string key)
        {
            cache.remove(key);
        }

        /// <summary>
        /// removes items by pattern
        /// </summary>
        /// <param name="pattern">pattern</param>
        public static void removebypattern(string pattern)
        {
            var regex = new regex(pattern, regexoptions.singleline | regexoptions.compiled | regexoptions.ignorecase);
            var keystoremove = new list<string>();

            foreach (var item in cache)
                if (regex.ismatch(item.key))
                    keystoremove.add(item.key);

            foreach (string key in keystoremove)
            {
                remove(key);
            }
        }

        /// <summary>
        /// clear all cache data
        /// </summary>
        public static void clear()
        {
            foreach (var item in cache)
                remove(item.key);
        }

框架提供了缓存的更新机制

查看memorycache的add方法:add(cacheitem, cacheitempolicy)

其中的参数cacheitempolicy有一个changemonitors属性, 该属性可选项为

system.runtime.caching.cacheentrychangemonitor
system.runtime.caching.filechangemonitor
system.runtime.caching.sqlchangemonitor

可以看出添加cache的时候可以设置此cache的几种类型的依赖

网上看到有filechangemonitor的例子, 现在小罗遇到的需求是需要根据系统表来更新缓存,

即数据库中的数据发生了改变, 此时更新本次添加的缓存

对上面的代码添加方法

        public static void setwithsql(string key, object data, string connstr, string sql, cacheentryremovedcallback callback)
        {
            if (data == null)
                return;

            cache.add(new cacheitem(key, data), sqlchangepolicy(connstr, sql, callback));
        }

 private static cacheitempolicy sqlchangepolicy(string connstr,string sql, cacheentryremovedcallback callback)
        {
            sqldependency.start(connstr);
            using (sqlconnection conn = new sqlconnection(connstr))
            {
                using (sqlcommand command = new sqlcommand(sql, conn))
                {
                    command.notification = null;
                    conn.open();

                    sqldependency dependency = new sqldependency(command);
                    dependency.addcommanddependency(command);

                    sqlchangemonitor monitor = new sqlchangemonitor(dependency);

                    cacheitempolicy policy = new cacheitempolicy();
                    policy.changemonitors.add(monitor);

                    command.executescalar();
                    policy.absoluteexpiration = datetime.now + timespan.fromminutes(60*24);
                    policy.removedcallback = callback;
                    return policy;
                }
            }
        }

添加cache项的时候, 传入sqlconnection和相应的sql, 目的是当sql对应的查询结果发生变化的时候, 清除此项缓存

注意是清除, 可以看到改方法有一个cacheentryremovedcallback参数,当此项被清除后会调用该callback方法

如果想"更新", 现在看到这个callback方法应该知道怎么做了

 

看着微软的帮助一步一步做下来简单, 但出了一个问题,就是刚add进去, 马上cacheentryremovedcallback方法就被调用了, 数据改变了? 确认一下没有,

继续研究帮助,

看一下sqlchangemonitor的构造函数, 参数是sqldependency

sqldependency是system.data.sqlclient 命名空间中的,

微软这样说:sqldependency 对象都表示应用程序和 sql server 实例之间的查询通知依赖项。 应用程序可以创建 sqldependency 对象并进行注册以接收通知通过 onchangeeventhandler 事件处理程序。

原来此对象是数据库中做监视和通知用的, 被"征用"过来的.

 

这就好办了, 根据帮助文档, 发现这个sql的要求真不是一般的严格

现在说一下这个"sql", 这个sql首先要求是一个select语句,然后:

  • 必须显式说明 select 语句中提取的列,并且表名必须限定为两部分组成的名称。注意,这意味着语句中引用的所有表都必须处于同一数据库中。

  • 语句不能使用星号 (*) 或 table_name.* 语法指定列。

  • 语句不能使用未命名列或重复的列名。

  • 语句必须引用基表。

  • 语句不能引用具有计算列的表。

  • 在 select 语句中提取的列不能包含聚合表达式,除非语句使用 group by 表达式。提供 group by 表达式时,选择列表便可以包含聚合函数 count_big() 或 sum()。但是,不能为可为空的列指定 sum()。语句不能指定 having、cube 或 rollup。

  • 在用作简单表达式的 select 语句中提取的列不能多次显示。

  • 语句不能包含 pivot 或 unpivot 运算符。

  • 语句不能包含 union、intersect 或 except 运算符。

  • 语句不能引用视图。

  • 语句不能包含下列任意一个:distinct、compute、compute by 或 into。

  • 语句不能引用服务器全局变量 (@@variable_name)。

  • 语句不能引用派生表、临时表或表变量。

  • 语句不能从其他数据库或服务器中引用表或视图。

  • 语句不能包含子查询、外部联接或自联接。

  • 语句不能引用下列大型对象类型:text、ntext 和 image。

  • 语句不能使用 contains 或 freetext 全文谓词。

  • 语句不能使用行集函数,包括 openrowset 和 openquery。

  • 语句不能使用下列任何一个聚合函数:avg、count(*)、max、min、stdev、stdevp、var 或 varp。

  • 语句不能使用任何具有不确定性的函数,包括排名函数和开窗函数。

  • 语句不能包含用户定义聚合。

  • 语句不能引用系统表或视图,包括目录视图和动态管理视图。

  • 语句不能包含 for browse 信息。

  • 语句不能引用队列。

  • 语句不能包含无法更改和无法返回结果的条件语句(如 where 1=0)。

  • 语句不能指定 readpast 锁提示。

  • 语句不能引用任何 service broker queue。

  • 语句不能引用同义词。

  • 语句不能具有基于 double/real 数据类型的比较或表达式。

  • 语句不得使用 top 表达式。

 

多吧, 还有个问题,就是要启用数据库的broker 

alter database database_name set trustworthy on with rollback immediate
alter database database_name set enable_broker with rollback immediate
alter authorization on database::database_name to sa

本文链接:https://2i3i.com/cache.html ,转载请注明来源地址。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇