【问题标题】:Using SqlDependency results in constant updates使用 SqlDependency 会导致不断更新
【发布时间】:2011-05-12 15:27:23
【问题描述】:

我从this MSDN page 中提取了一个示例,并且几乎一字不差地使用了它。运行时,代码可以正确编译,但changeCount 会不断递增,无论返回的数据是否确实发生了变化。当实际已经发生更改时,dataGridView1 正确反映了更改。为什么我的SqlDependency 似乎在循环触发,即使显然没有任何变化?

来源:

#region Using directives
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Text;
using System.Windows.Forms;
#endregion

namespace PreAllocation_Check
{
    public partial class Form1 : Form
    {
        int           changeCount = 0;
        const string  tableName = "MoxyPosition";
        const string  statusMessage = "Last: {0} - {1} changes.";
        DataSet       dataToWatch = null;
        SqlConnection MoxyConn = null;
        SqlCommand    SQLComm = null;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            if (CanRequestNotifications())
            {
                SqlDependency.Start(GetConnectionString());

                if (MoxyConn == null)
                    MoxyConn = new SqlConnection(GetConnectionString());

                if (SQLComm == null)
                {
                    SQLComm = new SqlCommand(GetSQL(), MoxyConn);

                    SqlParameter prm = new SqlParameter("@Quantity", SqlDbType.Int);
                    prm.Direction = ParameterDirection.Input;
                    prm.DbType = DbType.Int32;
                    prm.Value = 100;
                    SQLComm.Parameters.Add(prm);
                }

                if (dataToWatch == null)
                    dataToWatch = new DataSet();

                GetData();
            }
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            SqlDependency.Stop(GetConnectionString());
            if (MoxyConn != null)
                MoxyConn.Close();
        }

        private bool CanRequestNotifications()
        {
            try
            {
                SqlClientPermission SQLPerm = new SqlClientPermission(PermissionState.Unrestricted);
                SQLPerm.Demand();
                return true;
            }
            catch
            {
                return false;
            }
        }

        private string GetConnectionString()
        {
            return "server=***;database=***;user id=***;password=***";
        }

        private void GetData()
        {
            dataToWatch.Clear();
            SQLComm.Notification = null;
            SqlDependency SQLDep = new SqlDependency(SQLComm);
            SQLDep.OnChange += new OnChangeEventHandler(SQLDep_OnChange);

            using (SqlDataAdapter adapter = new SqlDataAdapter(SQLComm))
            {
                adapter.Fill(dataToWatch, tableName);
                dataGridView1.DataSource = dataToWatch;
                dataGridView1.DataMember = tableName;
            }
        }

        private string GetSQL()
        {
            return "SELECT PortID, CONVERT(money, SUM(PreAllocPos), 1) AS PreAllocation, CONVERT(money, SUM(AllocPos), 1) AS Allocation, CONVERT(money, SUM(PreAllocPos) - SUM(AllocPos), 1) AS PreLessAlloc " +
                   "FROM MoxyPosition " +
                   "WHERE CONVERT(money, PreAllocPos, 1) <> CONVERT(money, AllocPos, 1) " +
                   "GROUP BY PortID " +
                   "ORDER BY PortID ASC;";
        }

        void SQLDep_OnChange(object sender, SqlNotificationEventArgs e)
        {
            ISynchronizeInvoke i = (ISynchronizeInvoke)this;

            if (i.InvokeRequired)
            {
                OnChangeEventHandler tempDelegate = new OnChangeEventHandler(SQLDep_OnChange);
                object[] args = { sender, e };
                i.BeginInvoke(tempDelegate, args);
                return;
            }

            SqlDependency SQLDep = (SqlDependency)sender;
            SQLDep.OnChange -= SQLDep_OnChange;

            changeCount++;
            DateTime LastRefresh = System.DateTime.Now;
            label1.Text = String.Format(statusMessage, LastRefresh.TimeOfDay, changeCount);

            GetData();
        }
    }
}

编辑:值得注意的是,我要对其运行的数据库当前没有启用代理服务,因此为了测试我的代码,我备份了我的目标数据库并使用新名称,然后针对它运行ALTER DATABASE my_db_name SET ENABLE_BROKER。我的所有测试都在这个备用数据库上进行,这意味着我是它的唯一用户。

【问题讨论】:

    标签: c# sqldependency


    【解决方案1】:

    这是一个老问题,但问题是您的查询不符合要求。

    简答:
    将架构名称添加到表"FROM DBO.MoxyPosition " +

    更长的答案:
    可以看到一个list of requirements here,和创建索引视图非常相似。注册 SQL 依赖项后,如果它无效,则会立即触发通知,让您知道它是无效的。仔细想想,这是有道理的,因为 Visual Studio 怎么知道 SQL 引擎的内部要求是什么?

    因此,在您的SQLDep_OnChange 函数中,您需要查看触发依赖项的原因。原因在于e 变量(信息、来源和类型)。可以在此处找到有关事件对象的详细信息:

    对于您的具体情况,请注意MS describes Type 属性:

    Gets a value that indicates whether this notification is generated 
    because of an actual change, OR BY THE SUBSCRIPTION.
    

    【讨论】:

    • 非常感谢!这个答案让我从现在大约两天的搜索和尝试中解放出来。
    【解决方案2】:

    我遇到了类似的问题。事实证明,SELECT * FROM dbo.MyTable 导致更新不断触发。更改为 SELECT Id, Column1, Column2 FROM dbo.MyTable 解决了问题。

    您的查询中似乎没有使用*,但您可以尝试简化您的查询,看看是否还有问题。

    【讨论】:

      【解决方案3】:

      我对此没有答案,但你确实违反了至少一项规则:http://msdn.microsoft.com/en-us/library/aewzkxxh.aspx

      当您未能使用由两部分组成的表名时。将 MoxyPosition 更改为 dbo.MoxyPosition 并查看上面链接的规则。我希望它有所帮助,但有些东西告诉我这里有其他问题。

      【讨论】:

        【解决方案4】:

        查看处理程序中 SqlNotificationEventArgs 的类型(定义如下)。如果您看到它点击了数百次并且每次的类型都是订阅,那么您的 SQL 语句是错误的 - 请参阅其他帖子中的指南

        private void HandleOnChange(object sender, SqlNotificationEventArgs e)
        {
        ...
        
        var someType = e.Type; /*If it is Subscribe, not Change, then you may have your SQL statement wrong*/
        ...
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-08-25
          • 1970-01-01
          • 2022-01-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-11-22
          相关资源
          最近更新 更多