我希望用来SqlDependency在使用数据库的其他应用程序更改某些数据时收到通知.
public class DatabaseChangesNotification : IDisposable
{
    private static string chaineDeConnexion = ConfigurationManager.ConnectionStrings["TransfertContext"].ConnectionString;
    private static readonly Lazy<DatabaseChangesNotification> _instance = new Lazy<DatabaseChangesNotification>(() => new DatabaseChangesNotification());
    private DatabaseChangesNotification()
    {
        System.Diagnostics.Trace.WriteLine("--- SqlDependency START ---");
        SqlDependency.Start(chaineDeConnexion);
    }
    public void Dispose()
    {
        System.Diagnostics.Trace.WriteLine("--- SqlDependency STOP ---");
        SqlDependency.Stop(chaineDeConnexion);
    }
    public static DatabaseChangesNotification Instance
    {
        get 
        {
            return _instance.Value; 
        }
    }
    public void AbonnerNotification(string requete, OnChangeEventHandler eventhandler)
    {
        using (SqlConnection connection = new SqlConnection(chaineDeConnexion))
        {
            using (SqlCommand command = new SqlCommand(requete, connection) { Notification = null }) // clear existing notifications
            {
                connection.Open();
                var sqlDependency = new SqlDependency(command);
                OnChangeEventHandler delegateAutoRemove = null;
                delegateAutoRemove = (sender, e) => {
                    var dependency = sender as SqlDependency;
                    dependency.OnChange -= delegateAutoRemove;
                    eventhandler(sender, e); 
                };
                sqlDependency.OnChange += delegateAutoRemove;
                command.ExecuteNonQuery();
            }
        }
    }
}
所以,使用单行我可以注册一个事件处理程序:
DatabaseChangesNotification.Instance.AbonnerNotification(@"SELECT IdUtilisateur, Code, Nom, Prenom, NomComplet, Login, Synchroniser FROM dbo.Utilisateur", OnChanges);  
    public void OnChanges(object sender, SqlNotificationEventArgs e){
        System.Diagnostics.Trace.WriteLine("------------------------------ UPDATTEEEE -------------------------");
        System.Diagnostics.Trace.WriteLine("Info:   " + e.Info.ToString());
        System.Diagnostics.Trace.WriteLine("Source: " + e.Source.ToString());
        System.Diagnostics.Trace.WriteLine("Type:   " + e.Type.ToString());
        GlobalHost.ConnectionManager.GetHubContext<TransfertClientHub>().Clients.All.hello("users modified !");
        //AbonnementChanges();
    }
但我的问题是通知立即被解雇:
--- ABONNEMENT ---
------------------------------ UPDATTEEEE -------------------------
Info:   Query
Source: Statement
Type:   Subscribe
这就是我AbonnementChanges在我的事件处理程序中评论的原因OnChanges(或者它将无限循环).
我不知道问题出在哪里,因为我重置了通知({ Notification = null }),我的请求符合要求(https://msdn.microsoft.com/en-us/library/ms181122.aspx).
编辑:我想添加,select * from sys.dm_qn_subscriptions什么都不返回.
编辑:看起来它来自数据库配置,而不是来自我的实现,因为我尝试了另一个导致相同行为的实现:http://www.codeproject.com/Articles/144344/Query-Notification-using-SqlDependency -and-SqlCach
编辑:我没有看到它来自哪里,因为我使用SA是sysadmin并拥有所有权利,不是吗?
编辑:我尝试按照本教程定义与数据库的另一个连接:http://www.codeproject.com/Articles/12862/Minimum-Database-Permissions-Required-for-SqlDepen
所以我创造了两个角色:
EXEC sp_addrole 'sql_dependency_subscriber' 
EXEC sp_addrole 'sql_dependency_starter' 
-- Permissions needed for [sql_dependency_starter]
GRANT CREATE PROCEDURE to [sql_dependency_starter] 
GRANT CREATE QUEUE to [sql_dependency_starter]
GRANT CREATE SERVICE to [sql_dependency_starter]
GRANT REFERENCES on 
CONTRACT::[http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification]
  to [sql_dependency_starter] 
GRANT VIEW DEFINITION TO [sql_dependency_starter] 
-- Permissions needed for [sql_dependency_subscriber] 
GRANT SELECT to [sql_dependency_subscriber] 
GRANT SUBSCRIBE QUERY NOTIFICATIONS TO [sql_dependency_subscriber] 
GRANT RECEIVE ON QueryNotificationErrorsQueue TO [sql_dependency_subscriber] 
GRANT REFERENCES on 
CONTRACT::[http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification]
  to [sql_dependency_subscriber] 
然后我将user(production)添加到此角色:
- 确保我的用户是正确角色的成员.
EXEC sp_addrolemember 'sql_dependency_starter', 'production'
EXEC sp_addrolemember 'sql_dependency_subscriber', 'production'
但是通过这种联系,我有与以前相同的行为.通知是imediatly:
------------------------------ UPDATTEEEE -------------------------
Info:   Query
Source: Statement
Type:   Subscribe
编辑:我试过更简单的请求,如:SELECT Nom, Prenom FROM dbo.Utilisateur.以下是应该检查的表格的详细信息:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Utilisateur](
    [IdUtilisateur] [uniqueidentifier] ROWGUIDCOL  NOT NULL CONSTRAINT [DF_Utilisateur_IdUtilisateur]  DEFAULT (newid()),
    [Code] [varchar](10) NOT NULL,
    [Nom] [varchar](100) NOT NULL,
    [Prenom] [varchar](100) NULL,
    [NomComplet]  AS (([Prenom]+' ')+[Nom]),
    [Login] [varchar](50) NULL,
    [Synchroniser] [bit] NOT NULL CONSTRAINT [DF_Utilisateur_Synchroniser]  DEFAULT ((1)),
    [DATE_CREATION] [datetime] NOT NULL CONSTRAINT [DF__Utilisate__DATE___2AA1E7C7]  DEFAULT (getdate()),
    [DATE_DERNIERE_MODIF] [datetime] NOT NULL CONSTRAINT [DF__Utilisate__DATE___2B960C00]  DEFAULT (getdate()),
    [Desactive] [bit] NOT NULL CONSTRAINT [DF_Utilisateur_Desactive]  DEFAULT ((0)),
 CONSTRAINT [PK_Utilisateur] PRIMARY KEY CLUSTERED 
(
    [IdUtilisateur] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
我们可以看到有些列无法请求.这就是我不使用它的原因.
现在让我们检查一下SELECT Nom, Prenom FROM dbo.Utilisateur:
但那仍然行不通...... =(
最终编辑 - 解决方案:正如Jon Tirjan所说,这是由我的计算列引起的,NomComplet这对于Service Broker无效(即使我没有要求收到有关此列的更改的通知,这对我来说很奇怪).
Service Broker不适用于具有计算列的表.您需要NomComplet从表中删除,或将其更改为以另一种方式填充的实际列(触发器,存储过程等)
由于设置队列时发生错误,因此会立即触发通知.
| 归档时间: | 
 | 
| 查看次数: | 1395 次 | 
| 最近记录: |