【问题标题】:How to use SqlDependency and SignalR with 2 different databases using one function in C#?如何使用 C# 中的一个函数将 SqlDependency 和 SignalR 与 2 个不同的数据库一起使用?
【发布时间】:2015-12-25 04:11:56
【问题描述】:

我的场景是使用 2 个不同的 SqlDependencies 和 2 个不同的数据库连接,但调用一个函数。

我想使用 SqlDependency 获取第一个 DB 的更新,然后在第一个 DB 更改时同步第二个 DB,所以在第二个 DB 更新时,我想通过 Signalr 在客户端 Kendo Grid 加载更改 简单的过程正在工作,但是当第一次 DB1 更改时它同步 DB2 然后 DB2 在客户端通知以显示更改,但在 DB1 中获得第二次更改时也是相同的过程,SqlDependency 调用 3 次并通知客户端 3 次,对于 DB1 中的第 3 次更改,其 SqlDepency 调用 6 次或更多,意味着当 3 次之后的下一次更改时,其 SqlDependency 调用无限时间:

  1. EmailHub(DB2 集线器)

        public class EmailHub : Hub
        {
            private static string _connStringDB2 = ConfigurationManager.ConnectionStrings["MyDB2"].ToString();
    
            [HubMethodName("updateRecords")]
            public static void UpdateRecords()
            {
                IHubContext context = GlobalHost.ConnectionManager.GetHubContext<EmailHub>();
                context.Clients.All.getUpdates();
            }
    
        }
    
  2. HMailHub(DB1 集线器)

        public class HMailHub : Hub
        {
            private static string _connStringDB1 = ConfigurationManager.ConnectionStrings["MyDB1"].ToString();
    
            [HubMethodName("updateRecords")]
            public static void UpdateRecords()
            {
                IHubContext context = GlobalHost.ConnectionManager.GetHubContext<EmailHub>();
                context.Clients.All.getUpdates();
            }
    
        }
    
  3. GetEmailMessagesSQL(DB2 函数)

        public IEnumerable<EmailAflAwmMessageDM> GetEmailMessagesByAccountSQL(string emailid)
        {
            var messages = new List<EmailAflAwmMessageDM>();
    
            // sync hmailDb to LocalDb by EmailAccountId
            HMailServerSync objEmailSync = new HMailServerSync();
            objEmailSync.GetEmailMessagesByAccount(Guid.Parse(emailid));
    
            // stop all Sql dependencies before start new one
            SqlDependency.Stop(_connStringDB1);
            SqlDependency.Stop(_connStringDB2);
    
            //hmailDB service(DB1 sql function call)
            hmailsyncService(emailid);
    
            using (var connection = new SqlConnection(_connString))
            {
                connection.Open();
                using (var command = new SqlCommand(SQL.emailmessagesbyaccount_sql(), connection))
                {
                    command.Parameters.Add(new SqlParameter("@emailaccountid", emailid));
                    command.Notification = null;
                    var dependency = (dynamic)null;
                    SqlDependency.Start(_connStringDB2);
                    dependency = new SqlDependency(command);
                    dependency.OnChange += new OnChangeEventHandler(dependencyemailmessage_OnChange);
                    if (connection.State == ConnectionState.Closed)
                        connection.Open();
                    using (var reader = command.ExecuteReader())
                        messages = reader.Cast<IDataRecord>()
                            .Select(x => new EmailAflAwmMessageDM()
                            {
                                to_msg = x.GetString(0),
                                from_msg = x.GetString(1),
                                subject = x.GetString(2),
                                msg_date = x.GetDateTime(3)
    
                            }).ToList(); 
                 }
                connection.Close();
    
            }
            return messages;
        }
    
  4. DB2 SqlDependency

        private void dependencyemailmessage_OnChange(object sender, SqlNotificationEventArgs e)
        {
            if (e.Type == SqlNotificationType.Change)
            {
                EmailHub.UpdateRecords();
            }
        }
    
  5. HMailDB(DB1 SQL 函数)

    public void GetHmailMessagesByAccountSQL(int hmailid)
    {
        using (var connection = new SqlConnection(_connStringDB1))
        {
            connection.Open();
            using (var command = new SqlCommand(SQL.hmailmessages_sql(), connection))
            {
                command.Parameters.Add(new SqlParameter("@messageaccountid", hmailid));
                command.Notification = null;
                var dependency = (dynamic)null;
                SqlDependency.Start(_connStringDB1);
                dependency = new SqlDependency(command);
                dependency.OnChange += new OnChangeEventHandler(dependencyhmailmessage_OnChange);
                if (connection.State == ConnectionState.Closed)
                    connection.Open();
                var reader = command.ExecuteReader();
            }
            connection.Close();
        }
    
    }
    
  6. DB1 SqlDependency

        private void dependencyhmailmessage_OnChange(object sender, SqlNotificationEventArgs e)
        {
            if (e.Type == SqlNotificationType.Change)
            {
                EmailHub.UpdateRecords();
            }
        }
    
  7. 客户端代码(剑道网格)

       <div id="grid">
       </div>
    
       @Scripts.Render("~/bundles/signalr")
      <script src="~/signalr/hubs"></script>
    
      <script type="text/javascript">
      var emailid = '@TempData["DefaultEmailId"]'
      $(function () {
        // Declare a proxy to reference the hub.
        var notifications = $.connection.emailHub;
        // Create a function that the hub can call to broadcast messages.
        notifications.client.getUpdates = function () {
            alert("notification called");
            updateGridData();
        };
    
        // Start the connection.
        $.connection.hub.start().done(function () {
            alert("connection started")
            updateGridData();
        }).fail(function (e) {
            alert(e);
        });
    
        function updateGridData() {
            datasource = new kendo.data.DataSource({
                transport: {
                    read:
                        {
                            url: crudServiceBaseUrl + "EmailAflAwmMessage/getMessages/?emailid=" + emailid,
                            dataType: "json",
                        },
                    update:
                        {
                            url: crudServiceBaseUrl + "EmailAflAwmMessage/Put/",
                            type: "PUT",
                            parameterMap: function (options, operation) {
                                if (operation !== "read" && options.models) {
                                    return {
                                        models: kendo.stringify(options.models)
                                    };
                                }
                            }
                        },
                },
                schema:
                    {
                        model:
                            {
                                id: "EmailMessageId",
                                fields: {
                                    EmailMessageId: { editable: true, nullable: false, type: "guid" },
                                    subject: { editable: true, nullable: true, type: "string" },
                                    to_msg: { editable: true, nullable: false, type: "string" },
                                }
    
                            }
                    }
            });
    
            $("#grid").kendoGrid({
                dataSource: datasource,
                editable: "popup",
                toolbar: ["create"],
                columns: [
                {
                    field: "to_msg",
                    title: "to_msg",
                },
                {
                    field: "from_msg",
                    title: "from_msg",
                },
                {
                    field: "subject",
                    title: "subject",
                },
                {
                    field: "msg_date",
                    title: "msg_date",
                }
                ],
                height: "400px",
                pageable: {
                    refresh: true,
                    pageSizes: true,
                    buttonCount: 5
                },
            }).data("kendoGrid");
        }
    
    });
    

  8. Kendo Grid 中的 API 方法使用

    public IEnumerable<EmailAflAwmMessageDM> GetMessages(string emailid)
    {
        return objEmailSQLFunction.GetEmailMessagesByAccountSQL(emailid);
    }
    

我已经在上面详细解释了我的问题。 请指导我解决或建议我任何替代的优化解决方案,感谢您宝贵的时间和精力。 谢谢

【问题讨论】:

    标签: c# kendo-grid signalr sqldependency


    【解决方案1】:

    我在使用 SQL Dependency 时遇到了同样的问题。

    所以我创建了一个类来有效地使用它。

    注意:您应该拨打SqlDependency.Start(_connStringDB1);Application_Start(仅一次)

    public class LiveData
    {
        public string SprocOrQuery { get; set; }
        private Dictionary<string, object> par = new Dictionary<string, object>();
        public Dictionary<string, object> Parameters { get { return par; } set { par = value; } }
        public string SqlConn { get; set; }
        public Action<DataTable> ActionOnData { get; private set; }
        public bool EffectedOnly { get; set; }
        public DateTime EffectDate = DateTime.Now;
        public int EffectedCyles { get; private set; }
        public DataTable Data { get; private set; }
        public List<SqlNotificationInfo> Events { get; set; }
        public SqlNotificationInfo CurrentEvent { get; private set; }
    
        public LiveData() { }
        public LiveData(string sprocOrQuery, Dictionary<string, object> parameters = null, string connection = null)
        {
            SprocOrQuery = sprocOrQuery;
            Parameters = parameters;
            SqlConn = connection;
        }
    
        public Task Start(Action<DataTable> actionOnData = null)
        {
            return Task.Factory.StartNew(() =>
            {
                try
                {
                    if (ActionOnData == null) ActionOnData = actionOnData;
                    SqlConnection sqlConn = new SqlConnection(SqlConn);
                    using (SqlCommand cmd = new SqlCommand(SprocOrQuery, sqlConn) { CommandType = SprocOrQuery.Contains(" ") ? CommandType.Text : CommandType.StoredProcedure, CommandTimeout = 60 })
                    {
                        if (Parameters != null && Parameters.Count > 0)
                            foreach (var key in Parameters.Keys) cmd.Parameters.Add(new SqlParameter(key, Parameters[key]));
                        if (EffectedOnly) /* Sproc or Query must accept @UpdateDate parameter as DateTime */
                        {
                            if (cmd.Parameters.Contains("EffectDate")) cmd.Parameters["EffectDate"].Value = EffectDate;
                            else cmd.Parameters.Add(new SqlParameter("EffectDate", EffectDate));
                        }
                        cmd.Notification = null;
                        Data = new DataTable();
                        new SqlDependency(cmd).OnChange += OnChange;
                        if (sqlConn.State == ConnectionState.Closed) sqlConn.Open();
                        Data.Load(cmd.ExecuteReader(CommandBehavior.CloseConnection));
                    }
                    if ((Events == null || Events.Contains(CurrentEvent)))
                    {
                        if (EffectedCyles > 0) EffectDate = DateTime.Now;
                        EffectedCyles++;
                        if (ActionOnData != null) ActionOnData.Invoke(Data);
                    }
                }
                catch (Exception ex)
                {
                    Logger.LogException(ex);
                }
            });
        }
    
        private void OnChange(object sender, SqlNotificationEventArgs e)
        {
            CurrentEvent = e.Info;
            SqlDependency dependency = sender as SqlDependency;
            dependency.OnChange -= OnChange;
            Start();      
        }
    }
    

    用法

    new LiveData()
    {
        SprocOrQuery = @"SELECT 
                            t.[ID],
                            t.[CreateDate],
                            t.[UpdateDate] 
                        FROM 
                            dbo.Table t 
                            INNER JOIN dbo.Group g 
                                ON g.[ID] = t.[GroupID] 
                        WHERE 
                            t.[UpdateDate] >= @EffectDate",
        SqlConn = "SqlConnectionString",
        EffectedOnly = true,
        Events = new List<SqlNotificationInfo>() { SqlNotificationInfo.Update }
    }.Start(dt =>  
    {
        /* dt is the dataTable you get for every update */
        // you can run your dependencyemailmessage_OnChange logic here
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多