2010-09-16 96 views
9

我有一個C#程序查詢SQL Server數據庫的一些值。如何在數據庫更新時通知我的程序?

當前應用程序每分鐘查詢一次數據庫以確保表是最新的。

我希望能夠做的是,只有當數據庫已被更改/更新時,才能完成查詢。如何在數據庫中更新某些內容時通知我的程序?

感謝

回答

-1

如果「更新數據庫」你的意思是任何應用程序的任何更新,你的運氣了:這不是可行的。

但是,如果您的意思是您的應用程序所做的更改,很容易:您每次更新數據庫引發和事件並讓處理程序響應該事件。

+0

SqlDependancy正是這樣設計的。 – 2016-03-30 07:58:53

2

我希望能夠做的是,只有當數據庫已被更改/更新,才能完成查詢。當數據庫中更新某些東西時,如何通知我的程序。

數據庫沒有任何方式嚮應用程序推送通知。應用程序需要輪詢數據庫以檢查更新,然後適當地處理更新。

4

如果您使用的是SQL Server 2005及更高版本,則可以考慮使用SqlDependency對象。

它代表一個應用程序和SQL Server實例之間查詢通知相關性2005年

應用程序可以創建一個對象的SqlDependency和註冊通過OnChangeEventHandler事件處理程序接收通知。

Refer this link on MSDN for more information

然而,做注意到,MS提出反對其使用的警告。建議有一個緩存層,然後與該層協調使用SQLDependency。

SqlDependency設計用於ASP.NET或中間層服務,其中有相對少量的服務器具有對數據庫有活動的依賴關係。它不適用於客戶端應用程序,其中數百或數千臺客戶端計算機將SqlDependency對象設置爲單個數據庫服務器。

8

輪詢數據庫不是很優雅的解決方案。

來自ADO.NET的SqlDependency將對您的情況有用。它不使用輪詢,而是使用通知機制。 Service Broker會在數據庫中提供通知,因此需要在數據庫中啓用此服務。當指定的表更改(更新,刪除,插入..)時,將引發OnChange事件。)

下面是一個例子,如何使用的SqlDependency:

void Initialization() 
{ 
    // Create a dependency connection. 
    SqlDependency.Start(connectionString, queueName); 
} 

void SomeMethod() 
{ 
    // Assume connection is an open SqlConnection. 

    // Create a new SqlCommand object. 
    using (SqlCommand command=new SqlCommand(
     "SELECT ShipperID, CompanyName, Phone FROM dbo.Shippers", 
     connection)) 
    { 

     // Create a dependency and associate it with the SqlCommand. 
     SqlDependency dependency=new SqlDependency(command); 
     // Maintain the refence in a class member. 

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

     // Execute the command. 
     using (SqlDataReader reader = command.ExecuteReader()) 
     { 
      // Process the DataReader. 
     } 
    } 
} 

// Handler method 
void OnDependencyChange(object sender, 
    SqlNotificationEventArgs e) 
{ 
    // Handle the event (for example, invalidate this cache entry). 
} 

void Termination() 
{ 
    // Release the dependency. 
    SqlDependency.Stop(connectionString, queueName); 
} 

http://msdn.microsoft.com/en-us/library/62xk7953.aspx

這裏是如何使服務代理(請注意,您將有排他性數據庫來做到這一點 - 做最好它的SQL服務器重新啓動後): http://blogs.sftsrc.com/stuart/archive/2007/06/13/42.aspx (斷開鏈接)

可能的替代鏈接:http://technet.microsoft.com/en-us/library/ms166086(v=sql.105).aspx

+2

啓用服務代理的鏈接已中斷。 http://technet.microsoft.com/en-us/library/ms166086(v=sql.105).aspx – 2014-03-11 09:24:04

3

要更新某條記錄時獲得通知,請避免應用程序查詢您駕駛室使用的組件(在您的特定情況下爲SqlTableDependency)。這裏有一個例子:

public partial class Window1 : Window 
{ 
    private IList<Stock> _stocks; 
    private readonly string _connectionString = 
     "data source=.;initial catalog=myDB;integrated security=True"; 
    private readonly SqlTableDependency<Stock> _dependency; 

    public Window1() 
    { 
     this.InitializeComponent(); 
     this.McDataGrid.ItemsSource = LoadCollectionData(); 
     this.Closing += Window1_Closing; 

     var mapper = new ModelToTableMapper<Stock>(); 
     mapper.AddMapping(model => model.Symbol, "Code"); 

     _dependency = new SqlTableDependency<Stock>(_connectionString, "Stocks", mapper); 
     _dependency.OnChanged += _dependency_OnChanged; 
     _dependency.OnError += _dependency_OnError; 
     _dependency.Start(); 
    } 

    private void Window1_Closing(object sender, System.ComponentModel.CancelEventArgs e) 
    { 
     _dependency.Stop(); 
    } 

    private void _dependency_OnError(object sender, TableDependency.EventArgs.ErrorEventArgs e) 
    { 
     throw e.Error; 
    } 

    private void _dependency_OnChanged(
     object sender, 
     TableDependency.EventArgs.RecordChangedEventArgs<Stock> e) 
    { 
     if (_stocks != null) 
     { 
      if (e.ChangeType != ChangeType.None) 
      { 
       switch (e.ChangeType) 
       { 
        case ChangeType.Delete: 
         _stocks.Remove(_stocks.FirstOrDefault(c => c.Symbol == e.Entity.Symbol)); 
         break; 
        case ChangeType.Insert: 
         _stocks.Add(e.Entity); 
         break; 
        case ChangeType.Update: 
         var customerIndex = _stocks.IndexOf(
           _stocks.FirstOrDefault(c => c.Symbol == e.Entity.Symbol)); 
         if (customerIndex >= 0) _stocks[customerIndex] = e.Entity; 
         break; 
       } 

       this.McDataGrid.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() => 
       { 
        this.McDataGrid.Items.Refresh(); 
       })); 
      } 
     } 
    } 

    private IEnumerable<Stock> LoadCollectionData() 
    { 
     _stocks = new List<Stock>(); 

     using (var sqlConnection = new SqlConnection(_connectionString)) 
     { 
      sqlConnection.Open(); 
      using (var sqlCommand = sqlConnection.CreateCommand()) 
      { 
       sqlCommand.CommandText = "SELECT * FROM [Stocks]"; 

       using (var sqlDataReader = sqlCommand.ExecuteReader()) 
       { 
        while (sqlDataReader.Read()) 
        { 
         var code = sqlDataReader 
           .GetString(sqlDataReader.GetOrdinal("Code")); 
         var name = sqlDataReader 
           .GetString(sqlDataReader.GetOrdinal("Name")); 
         var price = sqlDataReader 
           .GetDecimal(sqlDataReader.GetOrdinal("Price")); 

         _stocks.Add(new Stock { Symbol = code, Name = name, Price = price }); 
        } 
       } 
      } 
     } 

     return _stocks; 
    } 

的觸發事件處理程序對每個INSERT UPDATE或DELETE對錶進行操作,你上報修改後的值。因此,如果您有興趣讓C#Datatable保持最新狀態,您可以簡單地從事件處理程序中獲取新數據。

+0

謝謝,似乎被修改爲每個案件,但不錯的代碼。 – 2016-08-28 10:47:46

相關問題