【问题标题】:Issue of multiple SQL notifications in ASP.Net web application on page refresh页面刷新时 ASP.Net Web 应用程序中的多个 SQL 通知问题
【发布时间】:2014-02-22 06:24:08
【问题描述】:

我在使用 SQL Server 通知时遇到问题。我正在 ASP.net 中开发一个 Web 应用程序,其中一个页面需要收到有关 SQL Server 数据库中一个表中的新条目的通知。我正在使用 SQL Server 通知服务和 Signal R 来实现此功能。我的网页似乎可以正常工作,获取有关新数据条目的更新。

刷新使用通知的页面时会出现问题。我发现数据库中单个条目的通知数量会随着刷新次数而增加。因此,如果我三次刷新页面,我会收到 3 个通知以获取一个条目。当连接的用户数量增加时,我有点担心这是否会给服务器带来负担。此外,如果在处理使用新条目更新页面的请求时出现错误,用户会收到多条具有相同文本的错误消息。我尝试调试我的代码,发现使用的 SqlDependency 对象的 on change 事件每次都会以不同的 ID 多次触发。以下是我的代码使用通知所做的简要概述 -

  1. 我使用的是 SQL Server 2012,并且为数据库设置了enable_broker

  2. global.asax 中,我使用application_startapplication_stop 事件来启动和停止SqlDependency

  3. 在页面代码中,我在页面加载时设置了一个新的SqlDependency 对象,使用命令对象来监视表的确切数据字段。

  4. onchangeSqlDependency 对象触发时,我使用 Signal R 集线器类通知 UI。然后我删除SqlDependency对象的OnChange处理程序,调用SqlDependency.Stop(connectionstring),将SqlDependency对象设置为空,调用SqlDependency.Start(connectionstring),最后使用命令对象再次设置SqlDependency对象进行更新数据。这整个设置为 nothing-stop-start-reset 对象是为了继续监控数据的变化。

上述步骤工作正常,但是当我刷新页面时,这些步骤会重复刷新次数。我通过更改代码和调试尝试了很多东西,但似乎没有任何解决问题的方法。现在我想知道是不是我错过了某个设置。

请帮我解决这个问题。如果需要任何其他信息,如环境、编码细节等,也请告诉我。

问候, 天美

【问题讨论】:

  • 遇到同样的问题,你解决了吗?
  • 我猜是调用注册sql依赖事件的问题,贴出你的代码,让我们帮忙
  • “在 global.asax 中,我使用 application_start 和 application_stop 事件来启动和停止 SqlDependency”。 - 所以每次页面刷新时,它都会创建一个新的(相同的)事件。有没有办法只在每个会话而不是每个页面加载一次?
  • 能否请您提供一些给您带来问题的代码?
  • 你解决过这个问题吗?你在使用连接池吗?

标签: sql sql-server-2008 notifications sqldependency


【解决方案1】:

我已经通过使用下面的代码解决了以下问题,它对我有用。

  1. SingletonDbConnect.cs
public class SingletonDbConnect
{
    private static SingletonDbConnect dbInstance;
    private static string connString = ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString;
    private readonly SqlConnection conn = new SqlConnection(connString);

    private SingletonDbConnect()
    {
    }

    public static SingletonDbConnect getDbInstance()
    {
        if (dbInstance == null)
        {
            dbInstance = new SingletonDbConnect();
        }
        return dbInstance;
    }

    public SqlConnection getDbConnection()
    {
        try
        {
            conn.Close();
            conn.Open();
        }
        catch (SqlException e)
        {

        }
        finally
        {
        }
        return conn;
    }

}
  1. SqlDependencyEvent.cs
public class SqlDependencyEvent
{
  internal static int PageLoadCounter = 0;
  public void getEmailMessagesByEmailId(Guid emailid)
    {

        SingletonDbConnect conn = SingletonDbConnect.getDbInstance();

        using (MembersController.command = new SqlCommand(SQL.emailmessagesbyaccount_sql(), conn.getDbConnection()))
        {

            MembersController.command.Notification = null;

            if (MembersController.dependency == null)
            {
                MembersController.dependency = new SqlDependency(MembersController.command);
                MembersController.dependency.OnChange += new OnChangeEventHandler(emailMessages_OnChange);
            }
            var reader = MembersController.command.ExecuteReader();
        }

        PageLoadCounter++;
    }
    private void emailMessages_OnChange(object sender, SqlNotificationEventArgs e)
    {
        if (e.Type == SqlNotificationType.Change)
        {

            if (MembersController.dependency != null)
            {
                MembersController.dependency.OnChange -= emailMessages_OnChange;
            }

            NotificationHub.EmailUpdateRecords();

            SingletonDbConnect conn = SingletonDbConnect.getDbInstance();
            using (MembersController.command = new SqlCommand(SQL.emailmessagesbyaccount_sql(), conn.getDbConnection()))
            {
                MembersController.command.Parameters.Add(new SqlParameter("@emailaccountid", defaultemailid));
                MembersController.command.Notification = null;

                MembersController.dependency = new SqlDependency(MembersController.command);
                MembersController.dependency.OnChange += new OnChangeEventHandler(emailMessages_OnChange);

                var reader = MembersController.command.ExecuteReader();

            }

            PageLoadCounter++;


        }
    }

}
  1. MembersController.cs
public class MembersController : Controller
{
    SingletonDbConnect conn = SingletonDbConnect.getDbInstance();

    internal static SqlCommand command = null;
    internal static SqlDependency dependency = null;

    //
    // GET: /Members/
    public ActionResult Index()
    {
        SqlDependency.Stop(conn.getDbConnection().ConnectionString);
        SqlDependency.Start(conn.getDbConnection().ConnectionString);
        return View();
    }
 }

它解决了我的问题并让我工作,即使我们刷新页面超过 1,但 SqlDependency 只会调用一次。 我使用了一个 MembersController 来启动和停止 SqlDependency,它是你自己的逻辑,你可以在 Global.ascx 中使用相同的代码而不是 MembersController.cs

我希望它能帮助您并解决问题。有问题可以问我谢谢。

【讨论】:

    【解决方案2】:

    这可能是由连接池引起的。它为池中打开的每个连接重新发出通知。您可以通过更改连接字符串属性来取消此特定服务的池:

    Pooling = False;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-21
      • 2014-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-31
      相关资源
      最近更新 更多