¿Cómo se supervisan los cambios en la tabla de SQL Server utilizando c #?

Tengo más de una aplicación accediendo a la misma base de datos y necesito que me notifiquen si una de estas aplicaciones cambia algo (actualizar, insertar) en una determinada tabla.

La base de datos y las aplicaciones no están en el mismo servidor.

Puede usar la SqlDependency Class . Su uso previsto es principalmente para páginas ASP.NET (baja cantidad de notificaciones de clientes).

 ALTER DATABASE UrDb SET ENABLE_BROKER 

Implemente el evento OnChange para recibir notificaciones:

 void OnChange(object sender, SqlNotificationEventArgs e) 

Y en código:

 SqlCommand cmd = ... cmd.Notification = null; SqlDependency dependency = new SqlDependency(cmd); dependency.OnChange += OnChange; 

Utiliza Service Broker (una plataforma de comunicación basada en mensajes) para recibir mensajes del motor de la base de datos.

En general, usaría Service Broker

Eso es trigger -> queue -> application (s)

Editar, después de ver otras respuestas:

FYI: “Notificaciones de consulta” se basa en Service Broker

Edit2:

Más enlaces

  • Notificación de eventos / agente de servicios
  • Equipo de Service Broker

En aras de la integridad, hay un par de otras soluciones que, en mi opinión, son más ortodoxas y están mejor establecidas que las soluciones que dependen de las clases SqlDependency (y SqlTableDependency). SqlDependency fue diseñado para la actualización de caché del servidor web, y por lo tanto no proporciona el tipo de resistencia bajo carga que requeriría de un productor de eventos.

En general, hay otras cuatro opciones que no se mencionan aquí:

  • Seguimiento de cambios
  • CDC
  • Dispara a las colas
  • CLR

Seguimiento de cambios

Fuente: https://docs.microsoft.com/en-us/sql/relational-databases/track-changes/about-change-tracking-sql-server

El seguimiento de cambios es un mecanismo de notificación liviano en el servidor SQL. Básicamente, un número de versión de base de datos se incrementa con cada cambio a cualquier dato. El número de versión se escribe en las tablas de seguimiento de cambios con una máscara de bits que incluye los nombres de las columnas que se cambiaron. Tenga en cuenta que el cambio real no se mantiene. La notificación solo contiene la información que una entidad de datos particular ha cambiado. Además, dado que el control de versiones de la tabla de cambios es acumulativo, los cambios individuales no se conservan y se sobrescriben con cambios más recientes. Esto significa que si una entidad cambia dos veces, el seguimiento de cambios solo sabrá sobre el cambio más reciente.

Para capturar estos cambios en c #, se debe usar el sondeo. Las tablas de cambios se pueden sondear y cada cambio se puede inspeccionar para ver si es interesante. Si es de interés, es necesario ir directamente a los datos para recuperar el estado actual.

Cambiar captura de datos

Fuente: https://technet.microsoft.com/en-us/library/bb522489(v=sql.105).aspx

La captura de datos modificados (CDC) es más poderosa pero más costosa que el seguimiento de cambios. La captura de datos modificados hará un seguimiento y notificará los cambios en función de la supervisión del registro de la base de datos. Debido a esto, CDC tiene acceso a los datos reales que se han cambiado y mantiene un registro de todos los cambios individuales.

De forma similar a cambiar el seguimiento, para capturar estos cambios en c #, se debe usar el sondeo. Sin embargo, en el caso de CDC, la información obtenida contendrá los detalles del cambio, por lo que no es estrictamente necesario volver a los datos en sí.

Dispara a las colas

Fuente: https://code.msdn.microsoft.com/Service-Broker-Message-e81c4316

Esta técnica depende de los factores desencadenantes en las tablas de las cuales se requieren notificaciones. Cada cambio disparará un disparador, y el desencadenante escribirá esta información en una cola del agente de servicio. La cola se puede conectar a través de C # utilizando el procesador de mensajes de Service Broker (muestra en el enlace anterior).

A diferencia del seguimiento de cambios o el CDC, los desencadenantes de las colas no dependen del sondeo y, por lo tanto, proporcionan eventos en tiempo real.

CLR

Esta es una técnica que he visto utilizada, pero no la recomendaría. Cualquier solución que dependa del CLR para comunicarse externamente es, en el mejor de los casos, un truco. El CLR fue diseñado para facilitar la escritura de código complejo de procesamiento de datos mediante el aprovechamiento de C #. No fue diseñado para conectarse en dependencias externas como bibliotecas de mensajes. Además, las operaciones vinculadas de CLR pueden romperse en entornos agrupados de maneras impredecibles.

Dicho esto, es bastante sencillo de configurar, ya que todo lo que tiene que hacer es registrar el conjunto de mensajes con CLR y luego puede llamar usando triggers o trabajos SQL.

En resumen…

Siempre me ha sorprendido que Microsoft se haya negado rotundamente a abordar este problema. El evento desde la base de datos al código debe ser una característica incorporada del producto de la base de datos. Teniendo en cuenta que Oracle Advanced Queuing combinado con el evento ODP.net MessageAvailable proporcionó eventos de bases de datos confiables a C # hace más de 10 años , esto es lamentable de MS.

El resultado de esto es que ninguna de las soluciones listadas para esta pregunta es muy buena. Todos ellos tienen inconvenientes técnicos y tienen un costo de instalación significativo. Microsoft, si está escuchando, solucione este lamentable estado de cosas.

SqlDependency no mira la base de datos que observa el SqlCommand que especifiques, por lo que si intentas digamos insertar valores en la base de datos en 1 proyecto y capturar ese evento en otro proyecto, no funcionará porque el evento fue del SqlCommand del El 1º proyecto no es la base de datos porque cuando creas una SqlDependency la vinculas a un SqlCommand y solo cuando se usa ese comando de ese proyecto crea un evento Change.

Use SqlTableDependency. Es un componente de CA # que genera eventos cuando un registro cambia. Puede encontrar otros detalles en: https://github.com/christiandelbianco/monitor-table-change-with-sqltabledependency

Es similar a .NET SqlDependency, excepto que SqlTableDependency genera eventos que contienen valores de tabla de base de datos modificados / eliminados o actualizados:

 string conString = "data source=.;initial catalog=myDB;integrated security=True"; using(var tableDependency = new SqlTableDependency(conString)) { tableDependency.OnChanged += TableDependency_Changed; tableDependency.Start(); Console.WriteLine("Waiting for receiving notifications..."); Console.WriteLine("Press a key to stop"); Console.ReadKey(); } ... ... void TableDependency_Changed(object sender, RecordChangedEventArgs e) { if (e.ChangeType != ChangeType.None) { var changedEntity = e.Entity; Console.WriteLine("DML operation: " + e.ChangeType); Console.WriteLine("ID: " + changedEntity.Id); Console.WriteLine("Name: " + changedEntity.Name); Console.WriteLine("Surname: " + changedEntity.Surname); } } 

Desde SQL Server 2005 tiene la opción de utilizar Query Notifications , que ADO.NET puede aprovechar, consulte http://msdn.microsoft.com/en-us/library/t9x04ed2.aspx

Tenga cuidado al usar la clase SqlDependency : tiene problemas con las pérdidas de memoria. Sin embargo, puede usar su propia realización con desencadenadores DDL y SQL Service Broker API o utilizar uno de los proyectos de código abierto, por ejemplo, SqlDependencyEx :

 int changesReceived = 0; using (SqlDependencyEx sqlDependency = new SqlDependencyEx( TEST_CONNECTION_STRING, TEST_DATABASE_NAME, TEST_TABLE_NAME)) { sqlDependency.TableChanged += (o, e) => changesReceived++; sqlDependency.Start(); // Make table changes. MakeTableInsertDeleteChanges(changesCount); // Wait a little bit to receive all changes. Thread.Sleep(1000); } Assert.AreEqual(changesCount, changesReceived); 

Espero que esto ayude.

se ve como una mala architecture todo el camino. tampoco ha especificado el tipo de aplicación a la que debe notificar (aplicación web / aplicación de consola / winforms / servicio, etc.)

sin embargo, para responder a su pregunta, hay varias formas de resolver esto. podrías usar:

1) indicaciones de fecha y hora si solo estaba interesado en asegurarse de que el siguiente conjunto de actualizaciones de la segunda aplicación no entre en conflicto con las actualizaciones de la primera aplicación

2) objeto de dependencia sql: consulte http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldependency.aspx para obtener más información

3) un servicio de notificación push personalizado al que múltiples clientes (web / winform / service) pueden suscribirse y recibir notificaciones de cambios

En resumen, debe utilizar la solución más simple, fácil y económica (en términos de esfuerzo) en función de la complejidad de los requisitos de notificación y el propósito para el que debe utilizarlos. No intente construir un sistema de notificación demasiado complejo si su único requisito es una simple concurrencia de datos (en ese caso, elija una solución simple basada en la marca de tiempo)

Otra forma muy simple de supervisar tablas es el control de versiones de tablas. El sistema ha demostrado funcionar en construcciones como la sincronización DNS. Para hacerlo funcionar, cree una tabla que contenga nombres de tabla y versiones de tabla como decimal o bigint. En cada tabla que necesite supervisar, cree un desencadenante al insertar, actualizar y eliminar que incrementará la versión de la tabla apropiada en la tabla de versiones cuando se ejecute. Si espera que alguna de las tablas supervisadas se modifique a menudo, debe aprovisionar para la reutilización de la versión. Finalmente, en su aplicación, cada vez que consulta una tabla supervisada, también consulta su versión y la almacena. Cuando va a modificar la tabla supervisada desde su aplicación, primero consulta su versión actual y procesa el cambio solo si la versión no se modifica. Puede hacer que el proc almacenado en SQL Server funcione para usted. Esta es una solución sólida extremadamente simple pero probada. Tiene un uso funcional específico (para garantizar la coherencia de los datos) y es liviano en cuanto a los recursos (no crías eventos intermediarios que no observarías) pero necesita una aplicación para verificar activamente los cambios en lugar de esperar pasivamente a que ocurra un evento.