我有一個C#程序查詢SQL Server數據庫的一些值。如何在數據庫更新時通知我的程序?
當前應用程序每分鐘查詢一次數據庫以確保表是最新的。
我希望能夠做的是,只有當數據庫已被更改/更新時,才能完成查詢。如何在數據庫中更新某些內容時通知我的程序?
感謝
我有一個C#程序查詢SQL Server數據庫的一些值。如何在數據庫更新時通知我的程序?
當前應用程序每分鐘查詢一次數據庫以確保表是最新的。
我希望能夠做的是,只有當數據庫已被更改/更新時,才能完成查詢。如何在數據庫中更新某些內容時通知我的程序?
感謝
如果「更新數據庫」你的意思是任何應用程序的任何更新,你的運氣了:這不是可行的。
但是,如果您的意思是您的應用程序所做的更改,很容易:您每次更新數據庫引發和事件並讓處理程序響應該事件。
我希望能夠做的是,只有當數據庫已被更改/更新,才能完成查詢。當數據庫中更新某些東西時,如何通知我的程序。
數據庫沒有任何方式嚮應用程序推送通知。應用程序需要輪詢數據庫以檢查更新,然後適當地處理更新。
如果您使用的是SQL Server 2005及更高版本,則可以考慮使用SqlDependency對象。
它代表一個應用程序和SQL Server實例之間查詢通知相關性2005年
應用程序可以創建一個對象的SqlDependency和註冊通過OnChangeEventHandler事件處理程序接收通知。
Refer this link on MSDN for more information
然而,做注意到,MS提出反對其使用的警告。建議有一個緩存層,然後與該層協調使用SQLDependency。
SqlDependency設計用於ASP.NET或中間層服務,其中有相對少量的服務器具有對數據庫有活動的依賴關係。它不適用於客戶端應用程序,其中數百或數千臺客戶端計算機將SqlDependency對象設置爲單個數據庫服務器。
輪詢數據庫不是很優雅的解決方案。
來自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
啓用服務代理的鏈接已中斷。 http://technet.microsoft.com/en-us/library/ms166086(v=sql.105).aspx – 2014-03-11 09:24:04
要更新某條記錄時獲得通知,請避免應用程序查詢您駕駛室使用的組件(在您的特定情況下爲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保持最新狀態,您可以簡單地從事件處理程序中獲取新數據。
謝謝,似乎被修改爲每個案件,但不錯的代碼。 – 2016-08-28 10:47:46
SqlDependancy正是這樣設計的。 – 2016-03-30 07:58:53