【问题标题】:**SignalR** SQLDependency Onchanged fired multiple times**SignalR** SQLDependency Onchanged 多次触发
【发布时间】:2024-01-04 10:54:01
【问题描述】:

我有一个带有 VS2013 和 .Net Framework 4.5.1 的 ASP.Net MVC 监控应用程序,它应该在每次数据库发生变化时自动刷新实时图表。当我打开一个浏览器实例时一切正常,但是当我在同一台机器或不同机器上打开另一个选项卡或浏览器时,它会多次触发 SQLDependency 事件。

这是我的 Repository.cs

  public class Repository
{
    private static string conString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ToString();
    public List<GetTakeInCount> UpdateTRTakeInData()
    {
        try
        {
            var lst = new List<GetTakeInCount>();
            using (SqlConnection con = new SqlConnection(conString))
            {

                using (var cmd = new SqlCommand(@"SELECT [Date],[TotalPlan],[TakeInQty],[OrderQty],[DelayedQty] FROM [dbo].[ProductTakeInData] Where [Production] = 'TR'", con))
                {
                    cmd.Notification = null;

                    if (con.State == ConnectionState.Closed)
                        con.Open();

                    SqlDependency dependency = new SqlDependency(cmd);
                    dependency.OnChange -= new OnChangeEventHandler(dependency_OnChange);
                    dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);

                    var rdr = cmd.ExecuteReader();
                    while (rdr.Read())
                    {
                        GetTakeInCount rowData = new GetTakeInCount();
                        rowData.TakeInQuantity = Convert.ToDouble(rdr["TakeInQty"].ToString());
                        rowData.Date = rdr["Date"].ToString();
                        rowData.PlanQuantity = rdr["TotalPlan"].ToString();
                        rowData.AccPlanQty = Convert.ToDouble(rdr["TotalPlan"].ToString());
                        rowData.OrderQty = Convert.ToDouble(rdr["OrderQty"].ToString());
                        rowData.DelayedQty = Convert.ToDouble(rdr["DelayedQty"].ToString());
                        lst.Add(rowData);
                    }
                    rdr.Dispose();
                }
            }

            return lst;
        }
        catch (Exception e)
        {
            throw e;
        }
    }

    private void dependency_OnChange(object sender, SqlNotificationEventArgs e) //this will be called when any changes occur in db table. 
    {
        if (e.Type == SqlNotificationType.Change)
            {
            //Call SignalR  
            MyHub mh = new MyHub();
            mh.UpdateChart();
        }
        SqlDependency dependency = sender as SqlDependency;
        if (dependency != null) dependency.OnChange -= new OnChangeEventHandler(dependency_OnChange);
    }

}

这是我的中心

[HubName("MyHub")]
    public class MyHub : Hub
    {

       public void UpdateChart()  
       {
            List<GetTakeInCount> data = new List<GetTakeInCount>();
            Repository rep = new Repository();
            data = rep.UpdateTRTakeInData();
            IHubContext context = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
            context.Clients.All.updateChartData(data);
        }  

    }

这是我的 js 东西:

 $(function () {
        // Declare a proxy to reference the hub.


        var chartConnection = $.connection.MyHub;
        $.connection.hub.logging = true;

        //debugger;
        // Create a function that the hub can call to broadcast messages.
        chartConnection.client.updateChartData = function () {
            updateChart();
            console.log('hub started')

        };
        // Start the connection.
        $.connection.hub.start();
        updateChart();

    });

        function updateChart()
        {                                         
    -- Update Chart Code ---
    }

有人可以帮忙吗?

【问题讨论】:

    标签: c# asp.net signalr signalr-hub sqldependency


    【解决方案1】:

    Ryan,您可以重新查看事件注销和注册部分。

    SqlDependency dependency = new SqlDependency(cmd); dependency.OnChange -= new OnChangeEventHandler(dependency_OnChange); dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);

    我认为最好有 SqlDependency 的单例对象,然后对其进行注销和注册。

    要做到这一点,您可以创建一个单例类,该类将为您提供 SqlDependency 的实例,而不是执行“new SqlDependency(cmd)”,您可以调用单例类的 getInstance(cmd) 方法并进行注销和注册那个。

    【讨论】:

    • 您好先生,我不知道如何为 sql 依赖做单例对象。你能给我一些建议或链接来指导我这样做吗?谢谢