gpt4 book ai didi

c# - Windows 服务中的 SqlDependency 未触发

转载 作者:太空宇宙 更新时间:2023-11-03 20:12:28 30 4
gpt4 key购买 nike

我正在尝试使用 SqlDependency 类监视数据库表的更改。虽然我一定错过了什么。我遵循了我在网上看到的所有示例,并查看了该站点上的所有问题。我只是不明白我错过了什么。以下是我在数据库上运行的初始命令,用于启用服务代理并创建队列和服务。

CREATE QUEUE ScheduleChangeQueue
GO

CREATE SERVICE ScheduleChangeService ON QUEUE ScheduleChangeQueue ([http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification])
GO

ALTER DATABASE [database] SET ENABLE_BROKER

在 C# 方面,我创建了一个类,该类具有一个调用以启动进程的静态 Setup 方法。这是相关代码:

public class SqlDependencyManager
{
private static bool DoesUserHavePermission()
{
var success = false;
try
{
Program.Log.Info("Retrieving SqlPermission to establish dependency...");

var clientPermission = new SqlClientPermission(System.Security.Permissions.PermissionState.Unrestricted);

// this will throw an error if the user does not have the permissions
clientPermission.Demand();

success = true;

Program.Log.Info("SqlPermission established. Continue setting up dependency.");
}
catch (Exception ex)
{
Program.Log.Error(ex, "SqlPermission not able to be established.");
}

return success;
}

public static void Setup()
{
if (!DoesUserHavePermission())
{
return;
}

var connectionString = ConfigurationManager.ConnectionStrings["ShowMakerPro"].ConnectionString;

// You must stop the dependency before starting a new one.
// You must start the dependency when creating a new one.
SqlDependency.Stop(connectionString);
SqlDependency.Start(connectionString);

using (var cn = new SqlConnection(connectionString))
{
using (var cmd = cn.CreateCommand())
{
cmd.CommandType = CommandType.Text;
//cmd.CommandText = "SELECT MAX(LastChangeTime) FROM Schedule WHERE ChannelID IN ( SELECT ID FROM Channels WHERE Type = 1 ) AND StartTime BETWEEN (GETDATE() - 7) AND (GETDATE() + 30)";
cmd.CommandText = "SELECT LastChangeTime FROM dbo.Schedule";
cmd.Notification = null;

// Creates a new dependency for the SqlCommand. Then creates attaches handler for the notification of data changes
new SqlDependency(cmd).OnChange += SqlDependency_OnChange;

cn.Open();

cmd.ExecuteReader();
}
}

Program.Log.Info("SQL Dependency set. Now monitoring schedule table for changes.");
}

private static void SqlDependency_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
// this will remove the event handler since the dependency is only for a single notification
((SqlDependency)sender).OnChange -= SqlDependency_OnChange;

ScheduleOutputterService.BuildSchedules();

Program.Log.Info("SQL Dependency triggered schedule rebuild. Resetting SqlDependency to monitor for changes.");

Setup();
}
}
}

我看到代码设置正常,OnChange 方法为订阅触发了一次,但之后我再也没有看到它触发。我手动进入数据库并更改 LastChangeTime 字段,希望它会强制触发事件,但没有任何反应。

有人可以阐明我搞砸的地方吗?我在网上看到有人说这在 Windows 窗体中工作正常,但他们在服务中也遇到了一些问题。

最佳答案

所以我终于找到了我的问题的答案,我想我应该列出我为达到这一点所采取的所有步骤,这样我后面的其他人也会有另一个地方寻找答案,因为我似乎无法在一个地方找到我所有的答案。

首先,我注意到在我的情况下,一旦设置了订阅,OnChange 事件就会立即触发。这就是我检查更改类型的原因,这样我就可以忽略这些事件。事实证明,忽略这些事件并不是一件好事,因为这些事件实际上是在试图告诉我一些事情。搜索我的值(value)观将我定向到这里:

http://msmvps.com/blogs/siva/archive/2011/11/22/subtle-sqldependency-notification-issue.aspx

这非常有值(value),因为它帮助我发现数据库中的某些选项一定存在问题。经过进一步检查,我注意到我的数据库设置为与 SQL Server 2000 兼容。这显然是我的第一个问题,因为这是 2005 年及更高版本的功能。所以我尝试将我的设置更改为高版本。这工作正常,但后来我仍然注意到我收到了同样的事件。然后我检查了我的数据库设置,发现它们没有设置为与运行服务代理所需的选项相匹配。您可以在此处查看所有必需的选项设置:

http://msdn.microsoft.com/en-us/library/ms181122(v=SQL.100).aspx

在我检查了所有这些并尝试做一些变通办法来获得正确的设置后,设置仍然失败。但是这次它失败了,因为更新不会保存。事实证明,客户端在有问题的表上有触发器,并且用于执行触发器的数据库设置与运行 QueryNotifications 所需的设置冲突。

长话短说,客户决定他们不想更改正在使用的所有触发器,因此他们放弃了这项工作。但是我学到了很多关于如何对 SqlDependency 和 ServiceBroker 进行故障排除的知识。希望我提供的这几个链接对其他人有所帮助。评论中提到了另外几个非常有用的链接,但我将在此答案中重新发布它们,以便您可以查看其他一些项目。

http://rusanu.com/2006/06/17/the-mysterious-notification/

http://rusanu.com/2005/12/20/troubleshooting-dialogs/

关于c# - Windows 服务中的 SqlDependency 未触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19106442/

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