繁体   English   中英

数据库更新后如何通知我的程序?

[英]How can I notify my program when the database has been updated?

我有一个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 server之后执行此操作): http //blogs.sftsrc.com/stuart/archive/2007/06/ 13 / 42.aspx 断开 链接)

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

如果您使用的是SQL Server 2005及更高版本,则可以考虑使用SqlDependency对象。

它表示应用程序与SQL Server 2005实例之间的查询通知依赖关系。

应用程序可以创建SqlDependency对象并注册以通过OnChangeEventHandler事件处理程序接收通知。

有关详细信息,请参阅MSDN上的此链接

但是,请注意MS对其使用的警告。 建议使用缓存层,然后与该层协调使用SQLDependency。

SqlDependency旨在用于ASP.NET或中间层服务,其中存在相对较少数量的服务器,这些服务器具有对数据库的活动依赖性。 它不是设计用于客户端应用程序,其中数百或数千台客户端计算机将为单个数据库服务器设置SqlDependency对象。

要在更新某些记录时获取通知,请避免应用程序查询您使用TableDependency组件的表(在您的特定情况下为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保持最新,那么您可以从事件处理程序中获取新数据。

我希望能够做的是只在数据库被更改/更新时才进行查询。当数据库中的某些内容更新时,我如何通知我的程序。

数据库没有任何方法将通知推送到应用程序。 应用程序需要轮询数据库以检查更新,然后适当地处理更新。

如果通过“对数据库的更新”表示任何应用程序的任何更新,那你就不走运了:这是不可行的。

但是,如果您的意思是应用程序所做的更改,则很容易:每次更新数据库引发和事件并让处理程序响应事件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM