【问题标题】:Getting data from SqlDependency从 SqlDependency 获取数据
【发布时间】:2013-01-30 09:54:43
【问题描述】:

我有一个表和一个正在等待新插入的 SqlDependency。

OnChange 会根据我的需要触发,但我不明白是否可以获取导致数据库更改的行。

SqlDependency sql命令:

SqlCommand cmd = new SqlCommand("SELECT id FROM dbo.DataRequests", m_sqlConn);

OnChange 代码:

private void OnChange(object sender, SqlNotificationEventArgs e)
{
    SqlDependency dependency = sender as SqlDependency;

    dependency.OnChange -= OnChange;

    Console.WriteLine("Info:   " + e.Info.ToString());
    Console.WriteLine("Source: " + e.Source.ToString());
    Console.WriteLine("Type:   " + e.Type.ToString());


    Console.WriteLine(DateTime.Now);

    GetMessages();

}

【问题讨论】:

  • 您的问题有助于找到我的问题的答案,即如何查找事件的来源和信息!
  • 由于您要定义检测更改的 SQL 命令,因此请对其进行结构化,以便了解更改的内容。例如SqlCommand cmd = new SqlCommand("SELECT id FROM dbo.DataRequests where changeAcknowledged = 0 ", m_sqlConn); 授予您可能没有对数据库的这种级别的控制。

标签: c# sqldependency


【解决方案1】:

看看这个组件: SqlTableDependency

对于 SQL Server 数据库表所做的每一次更改,C# 代码都会收到一个事件,其中包含更改的记录列表。

【讨论】:

    【解决方案2】:

    没有关于导致依赖项被触发的行的信息。

    我想作为一种解决方法,您始终可以在记录中添加时间戳并跟踪上次触发事件的时间。

    【讨论】:

    • 如果我在我的记录上创建一个时间戳,然后使用我的 SQL 字符串发送一个时间戳过滤器来注册一个依赖项,该怎么办?这样只有在指定时间之后插入的记录才会被返回。
    【解决方案3】:

    根据这篇文章,你不能:http://social.msdn.microsoft.com/Forums/en-US/sqlservicebroker/thread/07234067-73e1-4db5-a4e6-0f9f0bae22ae/

    您只能通过使用属性来缩小通知的原因

    提供的SqlNotificationEventArgs

    【讨论】:

      【解决方案4】:

      找到一个非常巧妙的解决方案here

      【讨论】:

        【解决方案5】:

        只需使用兼容跨平台 .NET 3.5 且开源的SqlDependencyEx。它使用数据库触发器和本机 Service Broker 通知来接收有关表更改的事件。这是一个用法示例:

        int changesReceived = 0;
        using (SqlDependencyEx sqlDependency = new SqlDependencyEx(
                  TEST_CONNECTION_STRING, TEST_DATABASE_NAME, TEST_TABLE_NAME)) 
        {
            sqlDependency.TableChanged += (o, e) => changesReceived++;
            sqlDependency.Start();
        
            // Make table changes.
            MakeTableInsertDeleteChanges(changesCount);
        
            // Wait a little bit to receive all changes.
            Thread.Sleep(1000);
        }
        
        Assert.AreEqual(changesCount, changesReceived);
        

        您可以获得更改通知以及更改的信息。详情请点击链接。

        【讨论】:

          【解决方案6】:

          希望对你有帮助:

               string commandString = string.Format("SELECT [Id] FROM [dbo].[Tech]");
               command = new SqlCommand(commandString, connection);
          
              private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
              {
                  SqlDependency dependency = (SqlDependency)sender;
                  dependency.OnChange -= dependency_OnChange;
          
                  this.Dispatcher.Invoke((System.Action)(() =>
                  {
          
                      if (e.Info.ToString().ToLower().Trim() == "insert")
                      {
                          GetData();
                          int NewTechID = TechIDs.Last();
                      }
          
                  }));
              }
          
              private void GetData()
              {
                  command.Notification = null;
                  SqlDependency dependency = new SqlDependency(command);
                  dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
          
                  command.Connection.Open();
                  using (SqlDataReader reader = command.ExecuteReader())
                  {
                      while (reader.Read())
                      {
                          TechIDs.add(int.Parse(reader.GetValue(0).ToString()));
                      }
                      reader.Close();
                  }
                  command.Connection.Close();
              }
          

          【讨论】:

            【解决方案7】:

            您可以使用临时表。 首先,您需要创建一个临时表,其中包含您需要继续调查的所有字段。类似:

            CREATE TABLE ##TempTab(
                [field1] [varchar](50) NULL,
                [field2] [varchar](50) NULL
            }
            

            请注意,在创建程序退出后,在外部 cose 中创建的表会自动删除,因此您无需在 formClosing 上删除它... 现在,在设置好 sqlDepency 东西之后,你必须填满你的临时表,这有点像开始场景的快照。 然后,每次触发 onChange 事件时,您只需将临时表与更新的情况进行比较。可能是这样的:

                select * from ##temptable left outer join mytable
            ON ##temptable.field1=myTable.field1 AND ##temptable.field2=myTable.field2
            WHERE myTable.field2 is null
            

            这将为您提供刚刚删除的所有行(或更改为旧值)。 另一边:

            select * from mytable left outer join ##temptable
                ON ##temptable.field1=myTable.field1 AND ##temptable.field2=myTable.field2
                WHERE ##temptable.field2 is null
            

            将为您提供刚刚添加(或更改为新值)的所有行。 在此比较之后,您只需要使用新值更新您的临时表(更快的方法是删除所有内容并插入所有值) 当然,如果您的程序将由不同的用户同时运行,您需要在临时表中处理 userid。

            【讨论】:

            • 这对于百万记录表来说可能不是更好的方法。
            猜你喜欢
            • 1970-01-01
            • 2018-12-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-12-23
            • 2013-10-11
            • 2011-02-24
            相关资源
            最近更新 更多