2010-09-16 17 views
9

Tengo un programa C# que consulta la base de datos de SQL Server para algunos valores.¿Cómo puedo notificar a mi programa cuando la base de datos se ha actualizado?

Actualmente, la aplicación consulta la base de datos cada minutos para asegurarse de que la tabla esté actualizada.

Lo que me gustaría poder hacer es que la consulta solo se realice cuando la base de datos ha sido modificada/actualizada. ¿Cómo notifico mi programa cuando algo se ha actualizado en la base de datos?

Gracias

Respuesta

-1

Si por "cambios a la base de datos" se refieren a cualquier actualización por cualquier aplicación, estás de suerte: no es factible.

Si, sin embargo, te refieres a los cambios realizados por tu aplicación, es fácil: cada vez que actualizas el aumento y evento de DB y los manejadores responden al evento.

+0

SqlDependancy es exactamente a lo que se diseñó. –

2

Lo que me gustaría hacer es que la consulta solo se realice cuando se haya cambiado/actualizado la base de datos. Cómo notifico mi programa cuando algo se actualiza en la base de datos.

No hay ningún medio para que la base de datos envíe notificaciones a la aplicación. La aplicación necesita sondear la base de datos para buscar actualizaciones y luego tratar las actualizaciones de manera apropiada.

4

Si está en SQL Server 2005 y superior, puede considerar usar el objeto SqlDependency.

representa una dependencia de notificación de consulta entre una aplicación y una instancia de SQL Server 2005.

Una aplicación puede crear un objeto SqlDependency y registrarse para recibir notificaciones a través del controlador de eventos OnChangeEventHandler.

Refer this link on MSDN for more information

Sin embargo, hacer notar la advertencia de que la EM pone en contra de su uso. Se recomienda tener una capa de almacenamiento en caché y luego usar SQLDependency en coordinación con esa capa.

SqlDependency fue diseñado para ser utilizado en ASP.NET o servicios de nivel medio donde hay un número relativamente pequeño de servidores que tienen dependencias activas contra la base de datos. No fue diseñado para su uso en aplicaciones cliente, donde cientos o miles de computadoras cliente tendrían objetos SqlDependency configurados para un solo servidor de base de datos.

8

La base de datos de sondeo no es una solución muy elegante.

SqlDependency de ADO.NET será útil en su caso. No utiliza el sondeo sino el mecanismo de notificación. Las notificaciones las proporciona Service Broker en su base de datos, por lo que deberá habilitar este servicio en su base de datos. El evento OnChange se producirá cuando cambien las tablas especificadas (actualizar, eliminar, insertar ...)

Aquí hay un ejemplo de cómo utilizar 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); 
} 

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

Aquí está cómo habilitar Service Broker (tenga en cuenta que va a tener la exclusividad en la base de datos para hacer eso - mejor hacer después de reiniciar el servidor SQL): http://blogs.sftsrc.com/stuart/archive/2007/06/13/42.aspx (enlace roto)

Posible enlace alternativo: http://technet.microsoft.com/en-us/library/ms166086(v=sql.105).aspx

+2

El enlace para habilitar el intermediario de servicios está roto. http://technet.microsoft.com/en-us/library/ms166086(v=sql.105).aspx –

3

Para recibir una notificación cuando se actualiza algún registro, evite que la aplicación consulte la tabla que utiliza el componente TableDependency de cabina (en su caso específico SqlTableDependency). He aquí un ejemplo:

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; 
    } 

El controlador de eventos se activa para cada actualización insertar o eliminar operación realizada sobre la mesa, que informar el valor modificado. Entonces, en caso de que esté interesado en mantener actualizada su tabla de datos C#, puede obtener los datos recientes del manejador de eventos.

+0

Gracias, parece que se ha modificado para cada caso pero buen código. –

Cuestiones relacionadas