我已经成功地使用SqlDependency,但只有在我不使用与SqlDependency无关的SQL事务
当我在事务中使用
IsolationLevel.ReadUncommited
时才能实现。当我在事务中使用
IsolationLevel.ReadUncommitted
(在下面的注释中重点说明)时,SqlDependency订阅将立即失败,并出现OnChange
通知:sqlNotificationEventArgs.Info = "Isolation";
sqlNotificationEventArgs.Source = "Statement";
sqlNotificationEventArgs.Type = "Subscribe";
当我移除隔离级别时,一切都按预期工作(当然,隔离级别不正确)。
这是我的相关代码:
private static string connString = "the connection string";
[MTAThread]
private static void Main(string[] args)
while(true)
{
using (var context = new LinqDataContext(connString))
{
var conn = context.Connection;
conn.Open();
/***********************************************************************/
/* Remove `IsolationLevel.ReadUncommitted` and the SqlDependency works */
/***********************************************************************/
using (var trans = conn.BeginTransaction(IsolationLevel.ReadUncommitted))
{
// simplified query, the real query uses UPDATE OUTPUT INSERTED
const string sqlCommand = "SELECT [Columns] FROM dbo.[TABLE] WHERE [Status] = 'ready'";
results = conn.Query({transaction: trans, sql: sqlCommand});
trans.Commit();
}
DoAwesomeStuffWithTheResults(results, context);
}
WaitForWork();
}
}
与SqlDependency相关的代码:
private static ManualResetEvent _quitEvent = new ManualResetEvent(false);
/// <summary>
/// Sets up a SqlDependency a doesn't return until it receives a Change notification
/// </summary>
private static void WaitForWork(){
// in case we have dependency running we need to go a head and stop it first.
SqlDependency.Stop(connString);
SqlDependency.Start(connString);
using (var conn = new SqlConnection(connString))
{
using (var cmd = new SqlCommand("SELECT [Status] From dbo.[TABLE]", conn))
{
cmd.Notification = null;
var dependency = new SqlDependency(cmd);
dependency.OnChange += dependency_OnDataChangedDelegate;
conn.Open();
cmd.ExecuteReader();
}
}
_quitEvent.WaitOne();
SqlDependency.Stop(connString);
}
private static void dependency_OnDataChangedDelegate(object sender, SqlNotificationEventArgs e)
{
((SqlDependency)sender).OnChange -= dependency_OnDataChangedDelegate;
_quitEvent.Set();
}
我觉得在设置SqlDependency之前,我已经妥善处理了上下文、连接和事务,但似乎情况并非如此。
我在这里做错了什么?
READ_UNCOMMITTED
设置了一个事务,所有后续语句都在该隔离级别下运行吗?或者可能是我没有正确处理事务(使用using
应该可以,不是吗?)?(我承认我可能没有完全理解一些核心 SQL 原则) - David Murdoch