C# 从SqlDependency获取数据

C# 从SqlDependency获取数据,c#,sqldependency,C#,Sqldependency,我有一个表和一个正在等待新插入的SqlDependency OnChange按我的需要启动,但我不知道是否有可能获取导致数据库更改的行 SqlDependency sql命令: SqlCommand cmd = new SqlCommand("SELECT id FROM dbo.DataRequests", m_sqlConn); 更改代码: private void OnChange(object sender, SqlNotificationEventArgs e) { SqlD

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

OnChange按我的需要启动,但我不知道是否有可能获取导致数据库更改的行

SqlDependency sql命令:

SqlCommand cmd = new SqlCommand("SELECT id FROM dbo.DataRequests", m_sqlConn);
更改代码:

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

}

根据这篇文章,你不能:

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


在提供的

中,没有关于导致触发依赖项的行的信息

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

我希望这对您有所帮助:

     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();
    }
您可以使用临时表。 首先,您需要创建一个临时表,其中包含需要调查的所有字段。比如:

CREATE TABLE ##TempTab(
    [field1] [varchar](50) NULL,
    [field2] [varchar](50) NULL
}
    select * from ##temptable left outer join mytable
ON ##temptable.field1=myTable.field1 AND ##temptable.field2=myTable.field2
WHERE myTable.field2 is null
请注意,在外部cose中创建的表类型会自动删除,因为创建者程序退出,所以您不需要在formClosing中删除它。。。 现在,在设置SQLDependency Stuff之后,您必须填充临时表,这类似于开始场景的快照。 然后,每次触发onChange事件时,您只需要将临时表与更新的情况进行比较。可能是这样的:

CREATE TABLE ##TempTab(
    [field1] [varchar](50) NULL,
    [field2] [varchar](50) NULL
}
    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。

查看此组件:


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

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

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

int changesReceived=0; 使用SqlDependencyEx SqlDependencyEx=new SqlDependencyEx 测试\连接\字符串、测试\数据库\名称、测试\表\名称 { sqlDependency.TableChanged+=o,e=>changesReceived++; sqlDependency.Start; //更改表格。 makeTableInsertDeleteChangesChangeScont; //请稍等,以接收所有更改。 线程1000; } Assert.AreEqualchangesCount,changesReceived;
您可以获取更改通知以及已更改的信息。请按照链接了解详细信息。

您的问题有助于找到我的问题的答案,即如何查找事件的来源和信息!!由于您正在定义检测更改的SQL命令,因此请对其进行结构化,以便了解更改的内容。例如,SqlCommand cmd=new SqlCommandSELECT id FROM dbo.DataRequests,其中changecogneded=0,m_sqlConn;当然,您可能没有对数据库的这种级别的控制。如果我在记录上创建一个timepstamp,然后用我的SQL字符串发送一个timestamp过滤器来注册依赖项,该怎么办?这样,只有在指定时间后插入的记录才会被返回。对于百万记录表来说,这可能不是更好的方法。