用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的查询接口的适配方法。做个笔记。
1
public class MapperAdapter2

{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 : DataObjectBase24

{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 : DataObjectBase40

{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 : DataObjectBase106

{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 : DataObjectBase127

{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

Cache Help#region Cache Help138

/**//// <summary>139
/// Gets the cache key.生成缓存KEY140
/// </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
#endregion185
}

浙公网安备 33010602011771号