我有以下代码:
class Program
{
static void Main()
{
var connection = new SqlConnection("myConnectionString");
connection.Open();
connection.StateChange += HandleSqlConnectionDrop;
Console.WriteLine("Hi");
Console.ReadLine();
}
private static void HandleSqlConnectionDrop(object connection, StateChangeEventArgs args)
{
Console.WriteLine("DB change detected");
}
}
我在SQL服务器实例运行时启动上面的代码。然后我继续执行
SHUTDOWN WITH NOWAIT;
在程序所连接的sql server实例上。然后我观察SQL服务器停止。但是,我从未看到检测到的" DB更改"输出中的消息。这是为什么?
旁白:如果我然后尝试对SQL连接执行操作,我将看到调用StateChange处理程序,但从未提前。有没有办法可以改变这种行为?
答案 0 :(得分:10)
什么时候调用DbConnection.StateChange?
您可以通过查看Microsoft参考源代码找到答案。
StateChange
函数引发了DbConnection.OnStateChange
事件。寻找对此函数的引用仅产生几个实例:
首先,在SqlConnection
课程中,仅Close
方法调用OnStateChange
。
然后在DbConnectionHelper.cs
文件中,有一个名为DBCONNECTIONOBJECT
的部分类。它看起来像是用于所有DbConnection
派生类,使用了一些构建时间的恶作剧。所以你可以认为它是SqlConnection
的一部分。在任何情况下,它仅从SetInnerConnectionEvent
函数中调用OnStateChange
。
据我所知(部分类无意义使得困难),SqlConnection.SetInnerConnectionEvent
仅从SqlConnectionFactory.SetInnerConnectionEvent
调用。并且从
DbConnectionClosed.TryOpenConnection
DbConnectionInternal.TryOpenConnectionInternal
DbConnectionInternal.CloseConnection
因此,总而言之 - 事件仅在响应客户端操作时引发 - 似乎没有对SQLConnection
内置的连接状态进行任何轮询。
有没有办法可以改变这种行为?
查看源代码,我看不到一个。正如其他人所建议的那样,你当然可以实施自己的民意调查。
答案 1 :(得分:3)
StateChange
事件用于连接状态,而不是数据库服务器的实例。要获取数据库服务器的状态,
当事件的状态发生变化时,会发生StateChange事件 关闭打开,或打开关闭。
来自MSDN:https://msdn.microsoft.com/en-us/library/system.data.common.dbconnection.statechange(v=vs.110).aspx
如果您要为数据库滚动自己的监视器,那么您可以考虑使用一种方法,如果连接可用则返回true / false并按计划ping该方法。你甚至可以用一个方法来包装一个方法,在一段时间后重复一次无限循环,并在这个"状态"之后提升它自己的事件。真的改变了。
这是一个来自另一个SO答案的快速方法,这是一个简单的方法:
/// <summary>
/// Test that the server is connected
/// </summary>
/// <param name="connectionString">The connection string</param>
/// <returns>true if the connection is opened</returns>
private static bool IsServerConnected(string connectionString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
try
{
connection.Open();
return true;
}
catch (SqlException)
{
return false;
}
}
}