gpt4 book ai didi

sql-server - 如何找出哪个SQLDependency触发了更改函数?

转载 作者:行者123 更新时间:2023-12-04 18:21:10 24 4
gpt4 key购买 nike

我正在使用 SQLDependency 类探索查询通知。构建一个简单的工作示例很容易,但我觉得我错过了一些东西。一旦我跳过了一个简单的单表/单依赖项示例,我就想知道如何找出哪个依赖项触发了我的回调?

我在解释时遇到了一些麻烦,因此我在下面提供了一个简单的示例。当调用 AChange() 时,我无法查看依赖项内的 sql,并且没有对关联缓存对象的引用。

那么男孩该做什么呢?

  • 选项 1 - 为每个我想要跟踪的对象创建一个不同的函数,并在回调中对缓存键(或相关信息)进行硬编码。这感觉很脏,并且消除了在不部署新代码的情况下添加新缓存项的可能性 - ewww。
  • 选项 2 - 使用依赖项 Id 属性和并行跟踪结构

我是不是错过了什么?这是 SQLDependency 结构中的缺陷吗?我已经看过 20 篇关于这个主题的不同文章,它们似乎都有相同的漏洞。有建议吗?

代码示例

public class DependencyCache{
public static string cacheName = "Client1";
public static MemoryCache memCache = new MemoryCache(cacheName);

public DependencyCache() {
SqlDependency.Start(connString);
}

private static string GetSQL() {
return "select someString FROM dbo.TestTable";
}

public void DoTest() {
if (memCache["TEST_KEY"] != null ) {
Debug.WriteLine("resources found in cache");
return;
}
Cache_GetData();
}

private void Cache_GetData() {
SqlConnection oConn;
SqlCommand oCmd;
SqlDependency oDep;
SqlDataReader oRS;
List<string> stuff = new List<string>();
CacheItemPolicy policy = new CacheItemPolicy();

SqlDependency.Start(connString);
using (oConn = new SqlConnection(connString) ) {
using (oCmd = new SqlCommand(GetSQL(), oConn) ) {
oDep = new SqlDependency(oCmd);
oConn.Open();
oRS = oCmd.ExecuteReader();

while(oRS.Read() ) {
resources.Add( oRS.GetString(0) );
}

oDep.OnChange += new OnChangeEventHandler (AChange);
}
}
memCache.Set("TEST_KEY", stuff, policy);
}

private void AChange( object sender, SqlNotificationEventArgs e) {
string msg= "Dependency Change \nINFO: {0} : SOURCE {1} :TYPE: {2}";
Debug.WriteLine(String.Format(msg, e.Info, e.Source, e.Type));

// If multiple queries use this as a callback how can i figure
// out WHAT QUERY TRIGGERED the change?
// I can't figure out how to tell multiple dependency objects apart

((SqlDependency)sender).OnChange -= Cache_SqlDependency_OnChange;
Cache_GetData(); //reload data
}
}

最佳答案

首先也是最重要的:必须在执行命令之前设置处理程序:

 oDep = new SqlDependency(oCmd);
oConn.Open();
oDep.OnChange += new OnChangeEventHandler (AChange);
oRS = oCmd.ExecuteReader();
while(oRS.Read() ) {
resources.Add( oRS.GetString(0) );
}

否则,您会出现一个窗口,通知可能会丢失,并且您的回调永远不会被调用。

现在关于您的问题:您应该为每个查询使用单独的回调。虽然这看起来很麻烦,但实际上使用 lambda 就很简单了。类似于以下内容:

oDep = new SqlDependency(oCmd);
oConn.Open();
oDep.OnChange += (sender, e) =>
{
string msg = "Dependency Change \nINFO: {0} : SOURCE {1} :TYPE: {2}";
Debug.WriteLine(String.Format(msg, e.Info, e.Source, e.Type));

// The command that trigger the notification is captured in the context:
// is oCmd
//
// You can now call a handler passing in the relevant info:
//
Reload_Data(oCmd, ...);
};
oRS = oCmd.ExecuteReader();
...

请记住始终检查通知来源、信息和类型。否则,当您因数据更改以外的原因(例如无效查询)收到通知时,您将面临令人厌恶的风险。作为附带评论,我想补充一点,好的缓存设计不会在失效时刷新缓存,而只是使缓存的项目失效,并让下一个请求实际获取新的项目。通过“主动”方法,即使不需要,您也会刷新缓存的项目,在访问它们之前多次刷新等等。我在示例中遗漏了错误处理和正确的线程同步(两者都是必需的)。

最后,看看LinqtoCache除了 LINQ 查询之外,它几乎可以完成您想要做的事情。

关于sql-server - 如何找出哪个SQLDependency触发了更改函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10655458/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com