使用SQL Cache Dependency 代替 Ibatisnet 提供的CacheModel

来源:互联网 发布:矩阵定价模型 编辑:程序博客网 时间:2024/06/15 17:08

    用IBatisNet作为持久层工具,有一个很好的好处就是很方便地使用它本身的缓存模型,可以控制在数据修改后缓存过期,但它的限制也是相当明显的,数据缓存和数据的更新操作必须在同一个应用程序域当中,当我在一台机器上缓存数据,而在另一台机器上修改数据(或者直接修改数据表)时就无法通知缓存过期了。这一个很棘手的问题,到底要不要使用缓存呢?在Asp.Net 2.0 当中有提供一个运行Sql Server的数据库更新通知缓存过期策略,(实现Cache SqlDependency,请参阅SQL Cache Dependency With SQL Server 2000),我可以将数据读取到UI层,然后再UI层再将数据缓存到HttpContext.Cache当中,再设置一个SqlDependency依赖,将它与指定的表做更新依赖。显然这样的做法是可行的,但如果就这样使用在当前的项目中,变得得不偿失。由于当前的DAL分为接口和实现,再结合Castle的IOC容器,实现组件的松耦合,可以随时改变接口的实现部分,尽管说做到改变数据库还是一个理论上的意愿,但是在UI层就将系统与Sql Server数据绑死(SqlDependency只支持Sql Server),显然与系统整体结构互相矛盾。最好的办法是在数据访问层直接就实现数据的缓存功能,这样数据是否实现缓存,如何缓存就对数据访问者来说就是透明的。还有一个需要考虑的问题是,对于数据访问层来说,它应该是独立于程序的架构(B/S,C/S),也就是对于一个程序来说,不管是C/S还是B/S结构的,应该可以使用同一个的数据访问层,这边就还需要考虑到HttpContext.Cache的使用问题了。不过这倒不是很难解决的问题,HttpContext.Cache的时候判断一下对象是否为空就行了。
    缓存KEY的生成也是一个大问题,Ibatisnet的缓存模型,可是做到同一个查询语句根据参数的值的来缓存数据,比如:这个查询的条件为1,而下次的查询条件仍为1时就会先去缓存读取数据,而如果为2时就会直接去数据库查询数据。在Ibatisnet中有一个专门的CacheKey类来做为缓存的key,而HttpContext.Cache只接收string类型的缓存KEY,在这边就必须根据Ibatisnet动态生成的Sql语句和参数值进行拼接做为缓存的key。为了保证数据一定时间不用后及时过期,不浪费太多内存,还应该缓每个缓存项添加相对时间过期策略。
  下面贴出对Ibatisnet的查询接口的适配方法。做个笔记。


  1public class MapperAdapter
  2    {
  3        public SqlMapper GetMapper()
  4        {
  5            return IBatisNet.DataMapper.Mapper.Instance(); 
  6        }

  7        private HttpContext BsContext = HttpContext.Current;
  8
  9        private SqlMapSession m_sqlSession;
 10        public MapperAdapter()
 11        {
 12            m_sqlSession = new SqlMapSession(GetMapper().DataSource);
 13        }

 14
 15        /// <summary>
 16        /// Queries for list.
 17        /// </summary>
 18        /// <param name="statementName">语句名称.</param>
 19        /// <param name="parameterObject">参数.</param>
 20        /// <param name="p_strTableName">缓存过期依赖表</param>
 21        /// <returns></returns>

 22        public GenericObjectListWrapper<T> QueryForList<T>(string statementName, object parameterObject, string p_strTableName)
 23            where T : DataObjectBase
 24        {
 25            return QueryForList<T>(statementName, parameterObject, -1-1, p_strTableName);
 26        }

 27
 28        /// <summary>
 29        /// Queries for list.
 30        /// </summary>
 31        /// <param name="statementName">Name of the statement.</param>
 32        /// <param name="parameterObject">The parameter object.</param>
 33        /// <param name="skipResult">The skip result.</param>
 34        /// <param name="maxResult">The max result.</param>
 35        /// <param name="p_strTableName">过期依赖表名</param>
 36        /// <returns></returns>

 37        public GenericObjectListWrapper<T> QueryForList<T>(string statementName, object parameterObject,
 38            int skipResult, int maxResult, string p_strTableName)
 39            where T : DataObjectBase
 40        {
 41            string cacheKey = GetCacheKey("QueryForList", statementName, parameterObject);
 42            GenericObjectListWrapper<T> m_list = Cache_Get(cacheKey) as GenericObjectListWrapper<T>;
 43            if (m_list == null)
 44            {
 45                m_list = new GenericObjectListWrapper<T>(GetMapper().QueryForList(statementName, parameterObject, skipResult, maxResult) as ObjectList);
 46                Cache_Add(cacheKey, m_list, p_strTableName);
 47            }

 48            return m_list;
 49        }

 50
 51        public IDictionary QueryForDictionary(string statementName, object parameterObject, string keyProperty, string p_strTableName)
 52        {
 53            return QueryForMap(statementName, parameterObject, keyProperty, p_strTableName);
 54        }

 55        /// <summary>
 56        /// Queries for dictionary.
 57        /// </summary>
 58        /// <param name="statementName">Name of the statement.</param>
 59        /// <param name="parameterObject">The parameter object.</param>
 60        /// <param name="keyProperty">The key property.</param>
 61        /// <param name="valueProperty">.</param>
 62        /// <param name="p_strTableName">过期依赖表名.</param>
 63        /// <returns></returns>

 64        public IDictionary QueryForDictionary(string statementName, object parameterObject, string keyProperty, string valueProperty,
 65            string p_strTableName)
 66        {
 67            return QueryForMap(statementName, parameterObject, keyProperty, valueProperty, p_strTableName);
 68        }

 69        /// <summary>
 70        /// Queries for map.
 71        /// </summary>
 72        /// <param name="statementName">Name of the statement.</param>
 73        /// <param name="parameterObject">The parameter object.</param>
 74        /// <param name="keyProperty">The key property.</param>
 75        /// <param name="p_strTableName">过期依赖表名.</param>
 76        /// <returns></returns>

 77        public IDictionary QueryForMap(string statementName, object parameterObject, string keyProperty, string p_strTableName)
 78        {
 79            return QueryForMap(statementName, parameterObject, keyProperty, null);
 80        }

 81
 82        /// <summary>
 83        /// Queries for map.
 84        /// </summary>
 85        /// <param name="statementName">Name of the statement.</param>
 86        /// <param name="parameterObject">The parameter object.</param>
 87        /// <param name="keyProperty">The key property.</param>
 88        /// <param name="valueProperty">The value property.</param>
 89        /// <param name="p_strTableName">过期依赖表名.</param>
 90        /// <returns></returns>

 91        public IDictionary QueryForMap(string statementName, object parameterObject, string keyProperty,
 92            string valueProperty, string p_strTableName)
 93        {
 94            string cacheKey = GetCacheKey("QueryForMap", statementName, parameterObject);
 95            IDictionary dictionary = Cache_Get(cacheKey) as IDictionary;
 96            if (dictionary == null)
 97            {
 98                dictionary = GetMapper().QueryForMap(statementName, parameterObject, keyProperty, valueProperty);
 99                Cache_Add(cacheKey, dictionary, p_strTableName);
100            }

101            return dictionary;
102        }

103
104        public T QueryForObject<T>(string statementName, object parameterObject, string p_strTableName)
105            where T : DataObjectBase
106        {
107            string cacheKey = GetCacheKey("QueryForObject", statementName, parameterObject);
108            T dataObject = Cache_Get(cacheKey) as T;
109            if (dataObject == null)
110            {
111                dataObject = GetMapper().QueryForObject(statementName, parameterObject) as T;
112                Cache_Add(cacheKey, dataObject, p_strTableName);
113            }

114            return dataObject;
115        }

116
117        /// <summary>
118        /// Queries for object.
119        /// </summary>
120        /// <param name="statementName">Name of the statement.</param>
121        /// <param name="parameterObject">The parameter object.</param>
122        /// <param name="resultObject">The result object.</param>
123        /// <param name="p_strTableName">过期依赖表名.</param>
124        /// <returns></returns>

125        public T QueryForObject<T>(string statementName, object parameterObject, T resultObject, string p_strTableName)
126            where T : DataObjectBase
127        {
128            string cacheKey = GetCacheKey("QueryForObject", statementName, parameterObject);
129            resultObject = Cache_Get(cacheKey) as T;
130            if (resultObject == null)
131            {
132                resultObject = GetMapper().QueryForObject(statementName, parameterObject, resultObject) as T;
133                Cache_Add(cacheKey, resultObject, p_strTableName);
134            }

135            return resultObject;
136        }

137        #region Cache Help
138        /// <summary>
139        /// Gets the cache key.生成缓存KEY
140        /// </summary>
141        /// <param name="p_strExecuteMethodName">Name of the P_STR execute method.</param>
142        /// <param name="statementName">Name of the statement.</param>
143        /// <param name="parameterObject">The parameter object.</param>
144        /// <returns></returns>

145        private string GetCacheKey(string p_strExecuteMethodName, string statementName, object parameterObject)
146        {
147            IMappedStatement mappedStatement = GetMapper().GetMappedStatement(statementName);
148            RequestScope requestScope = mappedStatement.Statement.Sql.GetRequestScope(parameterObject, m_sqlSession);
149
150            //
151            // 通过这个方法生成一个DbCommand,并且给所有的SQL参数指定值。如果没有调用此方法,requestScope.IDbCommand属性为空
152            //
153            mappedStatement.PreparedCommand.Create(requestScope, m_sqlSession, mappedStatement.Statement, parameterObject);
154            PreparedStatement preparedStatement = requestScope.PreparedStatement;
155
156            StringBuilder cacheKey = new StringBuilder(p_strExecuteMethodName + ":" + mappedStatement.Statement.Id + ";");
157            cacheKey.Append(" SQL:" + preparedStatement.PreparedSql);
158            cacheKey.Append(" Parameters:");
159            foreach (object obj in requestScope.IDbCommand.Parameters)
160            {
161                DbParameter parameter = (DbParameter)obj;
162                cacheKey.Append(string.Format("{0}={1};", parameter.ParameterName, parameter.Value));
163            }

164            return cacheKey.ToString();
165        }

166
167        protected virtual object Cache_Get(string p_strKey)
168        {
169            if (BsContext != null)
170            {
171                return BsContext.Cache.Get(p_strKey);
172            }

173            return null;
174        }

175
176        protected virtual void Cache_Add(string p_strKey, object p_value, string p_strTableName)
177        {
178            if (BsContext != null && p_value != null)
179            {
180                SqlCacheDependency m_sqlDependency = new SqlCacheDependency("CommonSqlDependency", p_strTableName);
181                BsContext.Cache.Insert(p_strKey, p_value, m_sqlDependency, DateTime.MaxValue, TimeSpan.Parse("00:30:00"));
182            }

183        }

184        #endregion

185    }
 
原创粉丝点击