2013-10-01 4 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(); 
     } 
    } 
} 

내가 코드 가져 오기 설정이 확인보고 onchange를 방법은 구독에 대해 한 번 해고 그러나 나는 그것이 그 후 화재 볼 수 없습니다 : 여기에 대한 코드입니다. 나는 수동으로 데이터베이스에 가서 LastChangeTime 필드를 변경하여 이벤트 발사를 강요하지만 아무 일도 일어나지 않기를 바란다.

내가 실수 한 부분을 누군가가 밝힐 수 있습니까? 나는 어떤 사람들이 온라인으로이 창문 형태로 잘 작동한다고 말하지만 서비스 중에도 문제가있다.

+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/

관련 문제