gpt4 book ai didi

c# - 如何使用 C# 中的一个函数将 SqlDependency 和 SignalR 与 2 个不同的数据库一起使用?

转载 作者:太空狗 更新时间:2023-10-29 23:50:09 33 4
gpt4 key购买 nike

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

我想使用 SqlDependency 通过第一个数据库获取更新,然后在第一个数据库更改时同步第二个数据库,然后在第二个数据库更新时我想通过 Signalr 在客户端加载更改 Kendo Grid简单的过程是有效的,但是当 DB1 第一次更改时,它会同步 DB2,然后 DB2 通知客户端以显示更改,而且当 DB1 第二次更改时,SqlDependency 调用 3 次并通知客户端 3 次,对于 DB1 中的第 3 次更改,其 SqlDepency 调用 6 次或更多次,这意味着当下一次更改在 3 次之后对其 SqlDepency 调用无限时间时:

  1. 电子邮件中心(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. 客户端代码(Kendo Grid)

       <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);
    }

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

最佳答案

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

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

注意:您应该在 Application_Start 调用 SqlDependency.Start(_connStringDB1);(仅一次)

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
});

关于c# - 如何使用 C# 中的一个函数将 SqlDependency 和 SignalR 与 2 个不同的数据库一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34459961/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com