2013-12-10 13 views
8

Tôi đã đoạn mã sau sử dụng SqlDependency để giám sát những thay đổi trong một cơ sở dữ liệu của tôi Nó hoạt động tuyệt vời, ngoại trừ mỗi chạy nó tạo riêng của mình Queue/Dịch vụ/Route với một guid trong cơ sở dữ liệu:Sử dụng SqlDependency với Queues tên

class:

class SqlWatcher 
{ 
    private string connectionString; 
    private string sqlQueue; 
    private string listenerQuery; 
    private SqlDependency dependency; 

    public SqlWatcher(string connectionString, string sqlQueue, string listenerQuery) 
    { 
     this.connectionString = connectionString; 
     this.sqlQueue = sqlQueue; 
     this.listenerQuery = listenerQuery; 
     this.dependency = null; 
    } 

    public void Start() 
    { 
     SqlDependency.Start(connectionString); 
     ListenForChanges(); 
    } 

    public void Stop() 
    { 
     SqlDependency.Stop(this.connectionString); 
    } 

    private void ListenForChanges() 
    { 
     //Remove existing dependency, if necessary 
     if (dependency != null) 
     { 
      dependency.OnChange -= onDependencyChange; 
      dependency = null; 
     } 

     SqlConnection connection = new SqlConnection(connectionString); 
     connection.Open(); 

     SqlCommand command = new SqlCommand(listenerQuery, connection); 

     dependency = new SqlDependency(command); 

     // Subscribe to the SqlDependency event. 
     dependency.OnChange += new OnChangeEventHandler(onDependencyChange); 

     SqlDependency.Start(connectionString); 

     command.ExecuteReader(); 

     //Perform this action when SQL notifies of a change 
     performAction(); 

     connection.Close(); 
    } 

    private void onDependencyChange(Object o, SqlNotificationEventArgs args) 
    { 
     if ((args.Source.ToString() == "Data") || (args.Source.ToString() == "Timeout")) 
     { 
      Console.WriteLine(System.Environment.NewLine + "Refreshing data due to {0}", args.Source); 
      ListenForChanges(); 
     } 
     else 
     { 
      Console.WriteLine(System.Environment.NewLine + "Data not refreshed due to unexpected SqlNotificationEventArgs: Source={0}, Info={1}, Type={2}", args.Source, args.Info, args.Type.ToString()); 
     } 
    } 

    private void performAction() 
    { 
     Console.WriteLine("Performing action"); 
    } 
} 

Thực hiện:

static void Main(string[] args) 
{ 
    string connectionString = @"<MY CONNECTION STRING>"; 
    string sqlQueue = @"NamesQueue"; 

    //Listener query restrictions: http://msdn.microsoft.com/en-us/library/aewzkxxh.aspx 
    string listenerQuery = "SELECT Value FROM dbo.Table WHERE Name = 'Test'"; 

    SqlWatcher w = new SqlWatcher(connectionString, sqlQueue, listenerQuery); 
    w.Start(); 
    Thread.Sleep(10000); 
    w.Stop(); 
} 

Thay vì tạo ra mọi hàng đợi/dịch vụ/tuyến đường riêng của mình, tôi muốn tạo ra chúng lên phía trước và sau đó nói với pro của tôi gram để sử dụng chúng.

tôi đã đi trước và tạo ra các đối tượng trên cơ sở dữ liệu:

CREATE QUEUE NamesQueue; 
CREATE SERVICE NamesService ON QUEUE NamesQueue; 
CREATE ROUTE NamesRoute WITH SERVICE_NAME = 'NamesService', ADDRESS = 'LOCAL'; 

và sửa đổi mã của tôi # C để sử dụng hàng đợi này và dịch vụ:

... 
SqlDependency.Start(connectionString, sqlQueue); 
... 
SqlDependency.Stop(this.connectionString, sqlQueue); 
... 
dependency = new SqlDependency(command, "service=NamesService;local database=<MY DB>", 0); 
... 
SqlDependency.Start(connectionString,sqlQueue); 
... 

Làm cho những thay đổi mã nguyên nhân không có hàng đợi để được được tạo khi đang chạy mã, tuy nhiên mã của tôi không còn hoạt động nữa và ứng dụng của tôi không nhận ra các thay đổi được thực hiện cho bảng/truy vấn của tôi.

Tôi đã dành nhiều ngày cố gắng tìm hiểu điều này mà không thành công, bất kỳ ai cũng có thể đưa ra lời khuyên nào không? Cảm ơn.

+0

Nhờ mã trong câu hỏi của bạn cuối cùng tôi đã có thể thiết lập SqlDependency thành công ... Cho đến bây giờ tôi vẫn nhận được các lỗi rất khó hiểu (hoặc không có lỗi gì cả, chỉ toàn bộ điều không hoạt động). Tôi tự hỏi tại sao rất khó để tìm thấy bất kỳ ví dụ tốt về điều này ... Dù sao, cảm ơn! – LambdaCruiser

Trả lời

6

Đã tìm ra - lỗi trong câu lệnh SQL CREATE của tôi. Tôi đã sử dụng:

CREATE SERVICE NamesService ON QUEUE NamesQueue; 

nhưng theo http://technet.microsoft.com/en-us/library/ms190332.aspx, lệnh CREATE DỊCH VỤ cần phải mất một tham số contract_name để có thể cho phép các hộp thoại khác để nhắm mục tiêu các dịch vụ được tạo ra.

Vì vậy, sử dụng bên dưới câu lệnh CREATE cố định vấn đề của tôi:

CREATE SERVICE NamesService 
ON QUEUE NamesQueue 
([http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification]) ; 
0

Hãy cẩn thận sử dụng SqlDependency lớp - nó có problems với rò rỉ bộ nhớ. Hovewer, bạn có thể sử dụng việc thực hiện mã nguồn mở của lớp SqlDependency - SqlDependencyEx. Nó sử dụng một trình kích hoạt cơ sở dữ liệu và thông báo môi giới dịch vụ gốc để nhận các sự kiện về các thay đổi của bảng. Đây là ví dụ về cách sử dụng:

int changesReceived = 0; 
using (SqlDependencyEx sqlDependency = new SqlDependencyEx(
      TEST_CONNECTION_STRING, TEST_DATABASE_NAME, TEST_TABLE_NAME)) 
{ 
    sqlDependency.TableChanged += (o, e) => changesReceived++; 
    sqlDependency.Start(); 

    // Make table changes. 
    MakeTableInsertDeleteChanges(changesCount); 

    // Wait a little bit to receive all changes. 
    Thread.Sleep(1000); 
} 

Assert.AreEqual(changesCount, changesReceived); 

Hy vọng điều này sẽ hữu ích.

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