我经常以以下形式运行查询:
select * from SomeTable where id=12345
页面后页我可能正在运行相同的查询,因为用户需要该行的值。通常我会获取一次并缓存它,但用户可以随时更改行,而其他用户也同时在SomeTable中进行更改,因此我无法对整个表进行缓存。我还有一个问题,即我们有一个用于Web服务器的集群,因此当缓存失效时,我无法在Web服务器上进行内部跟踪。
有没有办法检测到这一行发生了变化? SqlDependecyCache类可以在这里帮助单个行到多个Web服务器吗?是否有一些可以通知我的Web应用程序的触发器或其他范例?
我希望两全其美 - 网络服务器上的实时缓存更新,但我不想运行任何查询以查看该行是否已更改,因为我可以轻松地再次获取该行。
答案 0 :(得分:3)
您需要的是启用SqlCacheDependency作为@RenusRusanu提及。
我有几个工作示例on my Github site,随时可以浏览 the code under my LearningProjects (第三方编辑)
您需要先配置数据库才能使用SqlCacheDependency:
为了使用SQL依赖关系,我们需要在数据库中基本配置两件事:
创建包含表和存储过程的数据库基础结构,我们使用aspnet_regsql.exe
进行配置,如下所示:
/* For SQL Server authentication... */
aspnet_regsql.exe -S server -U user -P password -d database -ed
/* For Windows Authentication... */
aspnet_regsql.exe -S server -E -d database -ed
创建轮询信息,包括指定要监控的表和触发该表以填充所需的基础架构表
/* For SQL Server authentication... */
aspnet_regsql.exe -S server
-U user -P password -d database -t tableName -et
/* For Windows Authentication... */
aspnet_regsql.exe -S server
-E -d database -t tableName -et
代码配置
var s = new SqlCacheDependency("AdventureWorks", "Product");
HttpContext.Current.Cache.Insert(
"products",
h,
s,
Cache.NoAbsoluteExpiration,
Cache.NoSlidingExpiration);
AdventureWorks
名称是web.config文件中配置的sql依赖关系的名称
<caching>
<sqlCacheDependency enabled="true" pollTime="30000" >
<databases>
<add
name="AdventureWorks"
connectionStringName="AdventureWorksPolling" />
</databases>
</sqlCacheDependency>
</caching>
可以在pollTime
元素中配置<add ...
,并覆盖全局polltime
为了在使用此控件时启用缓存,您需要将DataSourceMode
属性设置为DataSet
。在这种情况下,您不需要按照之前的说明配置数据库
I just uploaded this example (full working example)
<asp:SqlDataSource runat="server" ID="sds"
ConnectionString="<%$ConnectionStrings:pubsConnectionString %>"
CacheDuration="30"
EnableCaching="true"
SelectCommand="select * from jobs"
DataSourceMode="DataSet"
OnSelecting="sds_Selecting">
</asp:SqlDataSource>
<div>
<asp:Literal runat="server" ID="msg" Mode="Encode"></asp:Literal>
</div>
<asp:GridView runat="server" DataSourceID="sds"></asp:GridView>
为了在使用SqlCacheDependency时有选择地触发触发器,您需要更新手动生成的触发器。
使用aspnet_regsql -t -et...
命令配置表时,会将触发器添加到指定的表中。此触发器负责填充SqlCacheDependency对象使用的AspNet_SqlCacheTablesForChangeNotification
表,以轮询数据库中的数据。
触发器如下:
ALTER TRIGGER [dbo].[jobs_AspNet_SqlCacheNotification_Trigger] ON [dbo].[jobs]
FOR INSERT, UPDATE, DELETE AS BEGIN
SET NOCOUNT ON
EXEC dbo.AspNet_SqlCacheUpdateChangeIdStoredProcedure N'jobs'
END
您可以更新触发器,以便在您感兴趣的行更新时调用dbo.AspNet_SqlCacheUpdateChangeIdStoredProcedureN'jobs'
存储过程
我不是SQL专家,但我认为很容易找到一种干净的方法来检测已经发生变化的行,例如google搜索我刚发现这个链接
Most efficient method to detect column change in MS SQL Server
答案 1 :(得分:2)
SqlCacheDependency
以及SqlDependency
可以完全按照您的描述进行操作。两者都基于Query Notifications,这项技术允许您的应用程序在更新行时从服务器接收通知。您甚至可以从LINQ开始利用它。
但是你需要保持警惕,缓慢经常变化的价值观会造成更多的伤害而不是好处。您应该只使用相当稳定的值来执行此操作。