我正在试图弄清楚如何使用SQL依赖关系(C#4.0)来“监听”数据库的更改。我在网上看到了很多东西,但它们似乎(自然地)用于使用依赖项来提取SQL依赖关系所依赖的相同数据。例如,this article。
我要做的是创建一个依赖项,当触发时,会产生许多不同的SQL“Select”查询(我可以将其存储在其他方法中等)。例如:我正在尝试设置一个监视表中行数的依赖项。当行数增加时,则执行x,y,z(即我的程序不关心行数是多少,只是它增加了,当它确实做了很多事情时)。
关于最好的方法是什么的任何想法?
编辑:我已经附上了我目前的代码。我试图找出如何分离设置SqlDependency和GetData()过程。目前,我认为我进入了一个无限循环,因为在我删除事件处理程序并重新运行“SetupSqlDependency()”之后,它又回到了事件处理程序
private void SetupSQLDependency()
{
// Tutorial for this found at:
// http://www.dreamincode.net/forums/topic/156991-using-sqldependency-to-monitor-sql-database-changes/
SqlDependency.Stop(connectionString);
SqlDependency.Start(connectionString);
sqlCmd.Notification = null;
// create new dependency for SqlCommand
SqlDependency sqlDep = new SqlDependency(sqlCmd);
sqlDep.OnChange += new OnChangeEventHandler(sqlDep_OnChange);
SqlDataReader reader = sqlCmd.ExecuteReader();
}
private void sqlDep_OnChange(object sender, SqlNotificationEventArgs e)
{
// FROM: http://msdn.microsoft.com/en-us/a52dhwx7.aspx
#region
// This event will occur on a thread pool thread.
// Updating the UI from a worker thread is not permitted.
// The following code checks to see if it is safe to
// update the UI.
/* ISynchronizeInvoke i = (ISynchronizeInvoke)this;
// If InvokeRequired returns True, the code
// is executing on a worker thread.
if (i.InvokeRequired)
{
// Create a delegate to perform the thread switch.
OnChangeEventHandler tempDelegate = new OnChangeEventHandler(sqlDep_OnChange);
object[] args = { sender, e };
// Marshal the data from the worker thread
// to the UI thread.
i.BeginInvoke(tempDelegate, args);
return;
}*/
#endregion
// Have to remove this as it only work's once
SqlDependency sqlDep = sender as SqlDependency;
sqlDep.OnChange -= sqlDep_OnChange;
// At this point, the code is executing on the
// UI thread, so it is safe to update the UI..
// 1) Resetup Dependecy
SetupSQLDependency();
}
答案 0 :(得分:5)
您可以连接SqlDependency.Change事件并在此事件处理程序中执行您喜欢的任何操作。事实上,这是做你想做的事的唯一方法,而且没有任何问题。
在伪代码中,它看起来像这样:
var dep = new SqlDependency(GetSqlQueryForMonitoring());
dep.Change += () => {
var data = ExecSql(GetDataQuerySql());
UpdateCache(data);
};
很简单。只需使用两个不同的查询。
编辑:在您的示例代码中,有一条评论说您正在UI线程上运行。为什么会这样呢?我对此表示怀疑。无论如何,您应该在重置依赖项之前运行查询,否则您将有可能发生并发失效。
我建议您从数据库中获取新数据,然后向ui发送消息以进行更新(Invoke)。