2012-02-24 34 views
15

Tôi đang làm việc với SQLDependency để thông báo cho tôi nếu có thay đổi trong Cơ sở dữ liệu. Sau khi chương trình khởi động nó hoạt động tốt. Khi tôi thực hiện thay đổi đầu tiên, sự kiện sẽ xảy ra. Wohoo ... thật tuyệt. Nhưng nếu tôi thực hiện thay đổi thứ hai, sự kiện sẽ không kích hoạt trở lại. Tôi đã tìm kiếm tất cả các trang web mà tôi nghĩ nhưng không tìm thấy bất cứ điều gì về vấn đề này. Chỉ tìm thấy sự cố khi sự kiện OnChange kích hoạt trong vòng lặp. Có ai giúp tôi không?SQLDependency_OnChange-Event chỉ kích hoạt một lần duy nhất

Dưới đây là một mã số ít mảnh:

private void GetStates() 
    { 
     if (!DoesUserHavePermission()) 
      return; 

     SqlDependency.Stop(con); 
     SqlDependency.Start(con); 

     using (SqlConnection cn = new SqlConnection(con)) 
     { 
      using (SqlCommand cmd = cn.CreateCommand()) 
      { 
       cmd.CommandType = CommandType.Text; 
       cmd.CommandText = "SELECT Bla, Bla2, ..FROM dbo.[BLA3]" 

       cmd.Notification = null; 
       cmd.Dispose(); 

       SqlDependency dep = new SqlDependency(cmd); 
       dep.OnChange += new OnChangeEventHandler(dep_OnChange); 

       cn.Open(); 

       using (SqlDataReader dr = cmd.ExecuteReader()) 
       { 
        state.Clear(); //In this Case "state" is a List<string> 
        while (dr.Read()) 
        { 
         state.Add(dr.GetString(0) + "|" + dr.GetInt32(3)); 
        } 
        dr.Dispose(); 
        dr.Close(); 
       }      
      } 
     } 
    } 

tôi OnChange-tổ chức sự kiện trông như thế này:

private void dep_OnChange(object sender, SqlNotificationEventArgs e) 
    { 
     SqlDependency dep = sender as SqlDependency; 
     dep.OnChange -= this.dep_OnChange; 

     using (SqlConnection cn = new SqlConnection(con)) 
     { 
      using (SqlCommand cmd = cn.CreateCommand()) 
      { 
       cmd.CommandType = CommandType.Text; 
       cmd.CommandText = "SELECT Bla, Bla2, ..FROM dbo.[BLA3]"; 

       cmd.Notification = null; 

       if (e.Type == SqlNotificationType.Change) 
       { 
        if (cn.State != ConnectionState.Open) 
        { 
         cn.Open(); 
        } 

        using (SqlDataReader dr = cmd.ExecuteReader()) 
        { 
         state.Clear(); // Clear and Refill the stringlist "state" 
         while (dr.Read()) 
         { 
          state.Add(dr.GetString(0) + "|" + dr.GetInt32(3)); 
         } 
        } 
       } 
       cn.Close(); 
      } 
     } 
     this.GetStates(); //to go ahead and wait for a new change 
    } 

đâu là vấn đề?

+0

bạn phải khởi tạo lại SqlDependency sau lần gọi sự kiện lần đầu. do đó, nó sẽ không phá vỡ cho sự kiện thứ 2 và như vậy. nó sẽ hoạt động hoàn hảo. – adnan

Trả lời

2

Không chắc chắn nếu đó là vấn đề của bạn, nhưng bạn vứt bỏ lệnh ngay sau khi bạn đã tạo ra nó:

using (SqlCommand cmd = cn.CreateCommand()) 
{ 
    ... 
    cmd.Dispose(); 

Nó trông giống như một lỗi.

+0

Mã ví dụ của Microsoft thực hiện tương tự. Tôi đã thử cả hai cách, và sự kiện này dường như vẫn chỉ cháy một lần. – BlueMonkMN

8

Tôi cũng đang gặp sự cố này. Bạn cần phải tạo một thực thể SqlDependency mới (sau khi hủy đăng ký thực thể hiện tại khỏi sự kiện OnChange) và sau đó chạy một lệnh ExecuteReader mới. Tôi đã có ý tưởng từ bài đăng này:

http://www.codeproject.com/Articles/12335/Using-SqlDependency-for-data-change-events

này thường có ý nghĩa, như một khi bạn đã được thông báo về một sự thay đổi mà bạn thường sẽ muốn tái truy vấn dữ liệu.

1

Hãy nhìn người bạn của tôi:

dep.OnChange -= this.dep_OnChange; 

bạn un đốt sự kiện của bạn; Điều đó không đúng sự thật; chỉ cần xóa dòng này;

+2

Anh ta cần phải làm điều đó, bởi vì một sự phụ thuộc mới sẽ được tạo ra mỗi lần. Đây là sự kiện thay đổi một lần. – Marshal

0

Trong GetStates():

SqlDependency.Stop(con); SqlDependency.Start(con);

những dòng này nên được thực hiện chỉ khi đăng ký phụ thuộc sql cho lần đầu tiên.

Giới hạn chúng khi bạn gọi phương thức từ sự kiện OnChange.

3

Trong phương thức private void dep_OnChange(object sender, SqlNotificationEventArgs e) sau khi bạn hủy đăng ký sự kiện dep_OnChange, bạn nên gọi lại private void GetStates(), để khởi tạo lại sự kiện dep.OnChange.

Các vấn đề liên quan