2013-10-01 98 views
1

我正在嘗試使用SqlDependency類監視數據庫表中的更改。雖然我一定錯過了一些東西。我已經遵循了我在網上看到的所有例子,並且已經查看了本網站上的所有問題。我只是看不到我缺少的東西。以下是我在數據庫上運行的初始命令,以啓用服務代理並創建隊列和服務。Windows服務中的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#方面,我創建了一個類,它具有一個被調用來啓動進程的靜態設置方法。下面是該代碼:

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

我看到的代碼獲取設置OK和方法的OnChange針對訂閱燒製一次,但後來我再也看不到它開火之後。我手動進入數據庫,並更改LastChangeTime字段,希望它會強制事件觸發,但沒有任何反應。

有人可以澄清我在哪裏搞砸嗎?我看到一些人在線上表示,這在Windows窗體中工作正常,但在服務中也存在一些問題。

+0

你在你的OnChange此評論:'//因爲依賴是僅適用於單個notification'也許這是原因,這將消除事件處理程序? – Serg

+0

@Serg這是必需的,因爲每次事件觸發它都會破壞依賴關係。您必須每次重新創建它以便在隨後的更改中繼續觸發它。 – spinon

+0

所以也許娛樂不起作用?對不起,如果我誤解你的代碼。 – Serg

回答

5

因此,我終於想出了我的問題的答案,我想我應該列出所有的步驟來達到這一點,所以在我身後的其他人也將有另一個地方尋找答案,因爲我似乎無法在一個地方找到我所有的答案。

首先,我注意到在我的情況下,只要訂閱被設置,OnChange事件就會立即啓動。這就是爲什麼我把檢查改變類型,所以我可以忽略這些事件。事實證明,忽視這些事件並不是件好事,因爲這些事件實際上是在試圖告訴我一些事情。這樣做對我的價值觀搜索指導我在這裏:

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

這是非常有價值的,因爲它讓我看到,一定有一個問題,我的一些數據庫選項。經過進一步檢查,我發現我的數據庫被設置爲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/