带有 signalR 的 SqlDependency 未持续触发 dependency_OnChange
SqlDependency with signalR not firing dependency_OnChange consistently
设置
•Visual Studio 2010
•IIS 8.5
•.NET Framework 4.6
•微软 SQL 服务器 2014
•IIS 上的 AppPool 帐户是 domain\web
我有一个监控数据库变化的网页 table。我正在使用 dependency_OnChange 来监视数据库并通过 signalR 将数据传递给用户。我在 dependency_OnChange 方法中设置了一个断点,在数千次数据库更新中它只被击中了几次。
在 web.config... 我正在使用 Integrated Security=True。
我的用户是 sql 框上的系统管理员。 (这仅用于概念验证)
在 Global.asax... 中指定队列名称并停止和启动 sqldependency
void Application_Start(object sender, EventArgs e)
{
var queuename = "Q_Name";
var sConn = ConfigurationManager.ConnectionStrings["singalR_ConnString"].ConnectionString;
SqlDependency.Stop(sConn, queuename);
SqlDependency.Start(sConn, queuename);
}
void Application_End(object sender, EventArgs e)
{
var queuename = "Q_Name";
var sConn = ConfigurationManager.ConnectionStrings["singalR_ConnString"].ConnectionString;
SqlDependency.Stop(sConn, queuename);
}
在代码后面...
public void SendNotifications()
{
//Identify Current User and Row No
string CurrentUser = GetNTName();
string message = string.Empty;
string conStr = ConfigurationManager.ConnectionStrings["singalR_ConnString"].ConnectionString;
using (SqlConnection connection = new SqlConnection(conStr))
{
string query = "SELECT [RowNo] FROM [dbo].[Test] WHERE [User] = @User";
string SERVICE_NAME = "Serv_Name";
using (SqlCommand command = new SqlCommand(query, connection))
{
// Add parameters and set values.
command.Parameters.Add("@User", SqlDbType.VarChar).Value = CurrentUser;
//Need to clear notification object
command.Notification = null;
//Create new instance of sql dependency eventlistener (re-register for change events)
SqlDependency dependency = new SqlDependency(command, "Service=" + SERVICE_NAME + ";", 0);
//SqlDependency dependency = new SqlDependency(command);
//Attach the change event handler which is responsible for calling the same SendNotifications() method once a change occurs.
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
message = reader[0].ToString();
}
}
}
//If query returns rows, read the first result and pass that to hub method - NotifyAllClients.
NotificationsHub nHub = new NotificationsHub();
nHub.NotifyAllClients(message);
}
private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
//Check type to make sure a data change is occurring
if (e.Type == SqlNotificationType.Change)
{
// Re-register for query notification SqlDependency Change events.
SendNotifications();
}
}
NotificationsHub.cs 页...
//Create the Hub
//To create a Hub, create a class that derives from Microsoft.Aspnet.Signalr.Hub.
//Alias that can call class from javascript. - i.e. var hub = con.createHubProxy('DisplayMessage');
[HubName("DisplayMessage")]
public class NotificationsHub : Hub //Adding [:Hub] let c# know that this is a Hub
{
//In this example, a connected client can call the NotifyAllClients method, and when it does, the data received is broadcasted to all connected clients.
//Create NotifyAllClients Method
//public means accessible to other classes
//void means its not returning any data
public void NotifyAllClients(string msg)
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<NotificationsHub>();
//When this method gets called, every single client has a function displayNotification() that is going to be executed
//msg is the data that is going to be displayed to all clients.
context.Clients.All.displayNotification(msg);
}
}
我在这里要做的第一件事是将 Sql 依赖设置重构为一个独立的方法,并从您的发送通知中调用它。 (SoC 和 DRY)因为如果您在其他地方创建其他 Sql 依赖项,它们会相互绊倒。其次,您正在创建一个新的 NotificationsHub,您应该获得当前活动的集线器。
DefaultHubManager hubManager = new DefaultHubManager();
hub = hubManager.ResolveHub("NotificationsHub");
hub.NotifyAllClients(message);
还有一种获取集线器的旧方法,但我不确定它是否仍然有效
GlobalHost.ConnectionManager.GetHubContext<NotificationsHub>()
我在这个答案中还有一个更简单版本的示例。
Polling for database changes: SqlDependency, SignalR is Good
如果您有任何问题,请告诉我。
设置
•Visual Studio 2010
•IIS 8.5
•.NET Framework 4.6
•微软 SQL 服务器 2014
•IIS 上的 AppPool 帐户是 domain\web
我有一个监控数据库变化的网页 table。我正在使用 dependency_OnChange 来监视数据库并通过 signalR 将数据传递给用户。我在 dependency_OnChange 方法中设置了一个断点,在数千次数据库更新中它只被击中了几次。
在 web.config... 我正在使用 Integrated Security=True。
我的用户是 sql 框上的系统管理员。 (这仅用于概念验证)
在 Global.asax... 中指定队列名称并停止和启动 sqldependency
void Application_Start(object sender, EventArgs e)
{
var queuename = "Q_Name";
var sConn = ConfigurationManager.ConnectionStrings["singalR_ConnString"].ConnectionString;
SqlDependency.Stop(sConn, queuename);
SqlDependency.Start(sConn, queuename);
}
void Application_End(object sender, EventArgs e)
{
var queuename = "Q_Name";
var sConn = ConfigurationManager.ConnectionStrings["singalR_ConnString"].ConnectionString;
SqlDependency.Stop(sConn, queuename);
}
在代码后面...
public void SendNotifications()
{
//Identify Current User and Row No
string CurrentUser = GetNTName();
string message = string.Empty;
string conStr = ConfigurationManager.ConnectionStrings["singalR_ConnString"].ConnectionString;
using (SqlConnection connection = new SqlConnection(conStr))
{
string query = "SELECT [RowNo] FROM [dbo].[Test] WHERE [User] = @User";
string SERVICE_NAME = "Serv_Name";
using (SqlCommand command = new SqlCommand(query, connection))
{
// Add parameters and set values.
command.Parameters.Add("@User", SqlDbType.VarChar).Value = CurrentUser;
//Need to clear notification object
command.Notification = null;
//Create new instance of sql dependency eventlistener (re-register for change events)
SqlDependency dependency = new SqlDependency(command, "Service=" + SERVICE_NAME + ";", 0);
//SqlDependency dependency = new SqlDependency(command);
//Attach the change event handler which is responsible for calling the same SendNotifications() method once a change occurs.
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
message = reader[0].ToString();
}
}
}
//If query returns rows, read the first result and pass that to hub method - NotifyAllClients.
NotificationsHub nHub = new NotificationsHub();
nHub.NotifyAllClients(message);
}
private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
//Check type to make sure a data change is occurring
if (e.Type == SqlNotificationType.Change)
{
// Re-register for query notification SqlDependency Change events.
SendNotifications();
}
}
NotificationsHub.cs 页...
//Create the Hub
//To create a Hub, create a class that derives from Microsoft.Aspnet.Signalr.Hub.
//Alias that can call class from javascript. - i.e. var hub = con.createHubProxy('DisplayMessage');
[HubName("DisplayMessage")]
public class NotificationsHub : Hub //Adding [:Hub] let c# know that this is a Hub
{
//In this example, a connected client can call the NotifyAllClients method, and when it does, the data received is broadcasted to all connected clients.
//Create NotifyAllClients Method
//public means accessible to other classes
//void means its not returning any data
public void NotifyAllClients(string msg)
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<NotificationsHub>();
//When this method gets called, every single client has a function displayNotification() that is going to be executed
//msg is the data that is going to be displayed to all clients.
context.Clients.All.displayNotification(msg);
}
}
我在这里要做的第一件事是将 Sql 依赖设置重构为一个独立的方法,并从您的发送通知中调用它。 (SoC 和 DRY)因为如果您在其他地方创建其他 Sql 依赖项,它们会相互绊倒。其次,您正在创建一个新的 NotificationsHub,您应该获得当前活动的集线器。
DefaultHubManager hubManager = new DefaultHubManager();
hub = hubManager.ResolveHub("NotificationsHub");
hub.NotifyAllClients(message);
还有一种获取集线器的旧方法,但我不确定它是否仍然有效
GlobalHost.ConnectionManager.GetHubContext<NotificationsHub>()
我在这个答案中还有一个更简单版本的示例。 Polling for database changes: SqlDependency, SignalR is Good
如果您有任何问题,请告诉我。