【问题标题】:SqlDependency with signalR not firing dependency_OnChange consistentlySqlDependency 与 signalR 没有一致地触发 dependency_OnChange
【发布时间】:2016-09-21 20:26:56
【问题描述】:

设置

•Visual Studio 2010

•IIS 8.5

•.NET Framework 4.6

•Microsoft SQL Server 2014

•IIS 上的 AppPool 帐户是 domain\web

我有一个监控数据库表变化的网页。我正在使用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);                                                       
    }

}

【问题讨论】:

    标签: asp.net sql-server iis signalr c#-2.0


    【解决方案1】:

    我在这里要做的第一件事是将 Sql Dependency 设置重构为一个独立的方法,并从您的发送通知中调用它。 (SoC 和 DRY),因为如果您在其他地方创建其他 SqlDependencies,它们将相互绊倒。其次,您正在创建一个新的 NotificationsHub,您应该获得当前活动的集线器。

    DefaultHubManager hubManager = new DefaultHubManager();
    hub = hubManager.ResolveHub("NotificationsHub");
    hub.NotifyAllClients(message);
    

    还有一种较旧的方式来获取集线器,但我不确定它是否仍然有效

    GlobalHost.ConnectionManager.GetHubContext<NotificationsHub>()
    

    我在这个答案中也有一个更简单版本的例子。 Polling for database changes: SqlDependency, SignalR is Good

    如果您有任何问题,请告诉我。

    【讨论】:

    • 感谢您的及时回复。
    • 我修改了我的代码以反映您关于解决集线器的建议。运行 hub.NotifyAllClients(message) 行时出现错误:对象未设置为对象的实例。我的 NotificationsHub 类不是静态的,所以我需要实例化该类的一个实例。我原来的例子是这样的: NotificationsHub nHub = new NotificationsHub();... 但现在我没有使用它。我该怎么做呢?另外,我很抱歉不知道这一点,但是我如何粘贴另一个代码示例以便向您展示我的 NotificationsHub 类?
    • 编辑您的原始问题并添加它。
    • @RobC 我在答案中添加了旧方法,但我不确定它是否仍然有效,或者它是否适用于您的情况。
    • 我已经在使用 [ GlobalHost.ConnectionManager.GetHubContext() ] 并且只有当类不是静态的并且我返回使用 [ NotificationsHub nHub = new NotificationsHub(); ...]。如何将解析中心与我的 NotificationsHub 集成:Hub?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多