我有一个用C#编写的程序,用于查询SQL Server数据库中的某些值。
目前该应用程序每分钟查询一次数据库以确保表格是最新的。
我希望能够在仅当数据库发生更改/更新时才执行查询。如何通知我的程序数据库已被更改?
谢谢
我有一个用C#编写的程序,用于查询SQL Server数据库中的某些值。
目前该应用程序每分钟查询一次数据库以确保表格是最新的。
我希望能够在仅当数据库发生更改/更新时才执行查询。如何通知我的程序数据库已被更改?
谢谢
轮询数据库并不是一个很优雅的解决方案。
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
以下是如何启用Service Broker的方法(请注意,您需要对数据库进行排他性操作才能这样做 - 最好在重新启动SQL服务器后执行此操作):http://blogs.sftsrc.com/stuart/archive/2007/06/13/42.aspx(链接已损坏)
可能的替代链接:http://technet.microsoft.com/en-us/library/ms166086(v=sql.105).aspx
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的最新状态,只需从事件处理程序获取最新数据即可。
如果您使用的是 SQL Server 2005 或更高版本,则可以考虑使用 SqlDependency 对象。
它表示应用程序和 SQL Server 2005 实例之间的查询通知依赖关系。
应用程序可以创建 SqlDependency 对象,并通过 OnChangeEventHandler 事件处理程序注册以接收通知。
但是,请注意 MS 对其使用的限制。建议先有缓存层,然后与该层协调使用 SQLDependency。
SqlDependency 是专为 ASP.NET 或中间层服务设计的,其中相对较少的服务器对数据库有活动依赖项。它不适用于客户端应用程序,在该应用程序中,数百或数千个客户端计算机会为单个数据库服务器设置 SqlDependency 对象。