Ich habe mehr als eine Anwendung, die auf dieselbe Datenbank zugreift, und ich muss benachrichtigt werden, wenn eine dieser Apps etwas in einer bestimmten Tabelle ändert (aktualisieren, einfügen).
Datenbank und Apps befinden sich nicht auf demselben Server.
c#
sql-server
monitoring
ToDayIsNow
quelle
quelle
Antworten:
Sie können die verwenden
SqlDependency Class
. Die beabsichtigte Verwendung ist hauptsächlich für ASP.NET-Seiten (geringe Anzahl von Client-Benachrichtigungen).ALTER DATABASE UrDb SET ENABLE_BROKER
Implementieren Sie das
OnChange
Ereignis, um benachrichtigt zu werden:void OnChange(object sender, SqlNotificationEventArgs e)
Und im Code:
SqlCommand cmd = ... cmd.Notification = null; SqlDependency dependency = new SqlDependency(cmd); dependency.OnChange += OnChange;
Es verwendet die
Service Broker
(eine nachrichtenbasierte Kommunikationsplattform), um Nachrichten vom Datenbankmodul zu empfangen.quelle
SqlSependency
so Gibt es einen besseren Weg , als diese Benachrichtigungen zu erhalten , wenn SQL Azure Datenänderungen oder wenn neue Daten eingefügt werden?Der Vollständigkeit halber gibt es einige andere Lösungen, die (meiner Meinung nach) orthodoxer sind als Lösungen, die auf den Klassen SqlDependency (und SqlTableDependency) basieren. SqlDependency wurde ursprünglich entwickelt, um das Aktualisieren verteilter Webserver-Caches zu vereinfachen, und wurde daher an andere Anforderungen angepasst, als wenn es als Event-Produzent konzipiert wäre.
Es gibt im Großen und Ganzen vier Optionen, von denen einige hier noch nicht behandelt wurden:
Tracking ändern
Quelle: https://docs.microsoft.com/en-us/sql/relational-databases/track-changes/about-change-tracking-sql-server
Änderungsverfolgung ist ein einfacher Benachrichtigungsmechanismus in SQL Server. Grundsätzlich wird bei jeder Änderung an Daten eine datenbankweite Versionsnummer erhöht. Die Versionsnummer wird dann mit einer Bitmaske einschließlich der Namen der geänderten Spalten in die Änderungsverfolgungstabellen geschrieben. Beachten Sie, dass die tatsächliche Änderung nicht beibehalten wird. Die Benachrichtigung enthält nur die Informationen, die eine bestimmte Datenentität geändert hat. Da die Versionierung der Änderungstabelle kumulativ ist, werden Änderungsbenachrichtigungen für einzelne Elemente nicht beibehalten und durch neuere Benachrichtigungen überschrieben. Dies bedeutet, dass bei einer zweimaligen Änderung einer Entität die Änderungsverfolgung nur über die letzte Änderung informiert ist.
Um diese Änderungen in c # zu erfassen, muss Polling verwendet werden. Die Änderungsverfolgungstabellen können abgefragt und jede Änderung überprüft werden, um festzustellen, ob sie von Interesse ist. Wenn es von Interesse ist, müssen Sie direkt zu den Daten gehen, um den aktuellen Status abzurufen.
Datenerfassung ändern
Quelle: https://technet.microsoft.com/en-us/library/bb522489(v=sql.105).aspx
Die Änderungsdatenerfassung (CDC) ist leistungsfähiger, aber am kostspieligsten als die Änderungsverfolgung. Die Änderungsdatenerfassung verfolgt und benachrichtigt Änderungen basierend auf der Überwachung des Datenbankprotokolls. Aus diesem Grund hat CDC Zugriff auf die tatsächlich geänderten Daten und zeichnet alle einzelnen Änderungen auf.
Ähnlich wie bei der Änderungsverfolgung muss die Abfrage verwendet werden, um diese Änderungen in c # zu erfassen. Im Fall von CDC enthalten die abgefragten Informationen jedoch die Änderungsdetails, sodass es nicht unbedingt erforderlich ist, zu den Daten selbst zurückzukehren.
Löst Warteschlangen aus
Quelle: https://code.msdn.microsoft.com/Service-Broker-Message-e81c4316
Diese Technik hängt von den Triggern in den Tabellen ab, für die Benachrichtigungen erforderlich sind. Bei jeder Änderung wird ein Trigger ausgelöst, und der Trigger schreibt diese Informationen in eine Service Broker-Warteschlange. Die Warteschlange kann dann über C # mithilfe des Service Broker-Nachrichtenprozessors verbunden werden (Beispiel im obigen Link).
Im Gegensatz zu Change Tracking oder CDC sind Trigger für Warteschlangen nicht auf Abfragen angewiesen und bieten somit Echtzeit-Eventing.
CLR
Dies ist eine Technik, die ich gesehen habe, aber ich würde sie nicht empfehlen. Jede Lösung, die sich bei der externen Kommunikation auf die CLR stützt, ist bestenfalls ein Hack. Die CLR wurde entwickelt, um das Schreiben von komplexem Datenverarbeitungscode durch die Nutzung von C # zu vereinfachen. Es wurde nicht entwickelt, um externe Abhängigkeiten wie Messaging-Bibliotheken zu verkabeln. Darüber hinaus können CLR-gebundene Vorgänge in Clusterumgebungen auf unvorhersehbare Weise unterbrochen werden.
Das Einrichten ist jedoch recht einfach, da Sie lediglich die Messaging-Assembly bei CLR registrieren müssen und dann mithilfe von Triggern oder SQL-Jobs abrufen können.
Zusammenfassend...
Es hat mich immer wieder überrascht, dass Microsoft sich standhaft geweigert hat, diesen Problembereich anzusprechen. Das Ereignis von der Datenbank zum Code sollte eine integrierte Funktion des Datenbankprodukts sein. In Anbetracht der Tatsache, dass Oracle Advanced Queuing in Kombination mit dem Ereignis ODP.net MessageAvailable vor mehr als 10 Jahren ein zuverlässiges Datenbankereignis für C # bereitstellte, ist dies für MS bedauerlich.
Das Ergebnis ist, dass keine der für diese Frage aufgeführten Lösungen sehr nett ist. Sie alle haben technische Nachteile und erhebliche Einrichtungskosten. Microsoft, wenn Sie zuhören, klären Sie bitte diesen traurigen Zustand.
quelle
Im Allgemeinen würden Sie Service Broker verwenden
Das ist Trigger -> Warteschlange -> Anwendung (en)
Bearbeiten, nachdem Sie andere Antworten gesehen haben:
Zu Ihrer Information: "Query Notifications" basiert auf dem Service Broker
Edit2:
Weitere Links
quelle
SqlSependency
so Gibt es einen besseren Weg , als diese Benachrichtigungen zu erhalten , wenn SQL Azure Datenänderungen oder wenn neue Daten eingefügt werden?Verwenden Sie SqlTableDependency. Es handelt sich um Ereignisse, die eine Komponente auslösen, wenn ein Datensatz geändert wird. Weitere Details finden Sie unter: https://github.com/christiandelbianco/monitor-table-change-with-sqltabledependency
Es ähnelt .NET SqlDependency, außer dass SqlTableDependency Ereignisse auslöst, die geänderte / gelöschte oder aktualisierte Datenbanktabellenwerte enthalten:
string conString = "data source=.;initial catalog=myDB;integrated security=True"; using(var tableDependency = new SqlTableDependency<Customers>(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<Customers> 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); } }
quelle
Seien Sie vorsichtig mit der SqlDependency- Klasse - sie hat Probleme mit Speicherlecks.
Verwenden Sie einfach eine plattformübergreifende, .NET 3.5-, .NET Core-kompatible und Open Source-Lösung - SqlDependencyEx . Sie können Benachrichtigungen sowie geänderte Daten erhalten (Sie können über Eigenschaften im Benachrichtigungsereignisobjekt darauf zugreifen). Sie können die Operationen DELETE \ UPDATE \ INSERT auch einzeln oder zusammen ausführen.
Hier ist ein Beispiel dafür, wie einfach es ist, SqlDependencyEx zu verwenden :
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);
Bitte folgen Sie den Links für Details. Diese Komponente wurde in vielen Anwendungen auf Unternehmensebene getestet und hat sich als zuverlässig erwiesen. Hoffe das hilft.
quelle
SqlDependency überwacht nicht die Datenbank, sondern den von Ihnen angegebenen SqlCommand. Wenn Sie also versuchen, beispielsweise Werte in die Datenbank in einem Projekt einzufügen und dieses Ereignis in einem anderen Projekt zu erfassen, funktioniert dies nicht, da das Ereignis vom SqlCommand aus stammt 1º-Projekt nicht die Datenbank, da beim Erstellen einer SqlDependency diese mit einem SqlCommand verknüpft wird und nur bei Verwendung dieses Befehls aus diesem Projekt ein Änderungsereignis erstellt wird.
quelle
Seit SQL Server 2005 haben Sie die Möglichkeit, Abfragebenachrichtigungen zu verwenden , die von ADO.NET genutzt werden können (siehe http://msdn.microsoft.com/en-us/library/t9x04ed2.aspx)
quelle
sieht den ganzen Weg nach schlechter Architektur aus. Außerdem haben Sie nicht angegeben, bei welchem App-Typ Sie benachrichtigen müssen (Web-App / Konsolen-App / Winforms / Service usw. usw.).
Um Ihre Frage zu beantworten, gibt es jedoch mehrere Möglichkeiten, dies zu lösen. Du könntest benutzen:
1) Zeitstempel, wenn Sie nur daran interessiert waren, sicherzustellen, dass die nächsten Updates aus der zweiten App nicht mit den Updates aus der ersten App in Konflikt stehen
2) SQL-Abhängigkeitsobjekt - Weitere Informationen finden Sie unter http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldependency.aspx
3) Ein benutzerdefinierter Push-Benachrichtigungsdienst, den mehrere Clients (Web / Winform / Service) abonnieren und über Änderungen benachrichtigt werden können
Kurz gesagt, Sie müssen die einfachste und einfachste und kostengünstigste (in Bezug auf den Aufwand) Lösung verwenden, basierend darauf, wie komplex Ihre Benachrichtigungsanforderungen sind und für welchen Zweck Sie sie verwenden müssen. Versuchen Sie nicht, ein übermäßig komplexes Benachrichtigungssystem aufzubauen, wenn eine einfache Datenparallelität Ihre einzige Anforderung ist (in diesem Fall entscheiden Sie sich für eine einfache zeitstempelbasierte Lösung).
quelle
Eine andere, sehr einfache Möglichkeit zur Überwachung von Tabellen ist die Tabellenversionierung. Das System funktioniert nachweislich in Konstruktionen wie der DNS-Synchronisation. Damit dies funktioniert, erstellen Sie eine Tabelle mit Tabellennamen und Tabellenversionen als
decimal
oderbigint.
Erstellen Sie in jeder Tabelle, die überwacht werden muss, einen Auslöser beim Einfügen, Aktualisieren und Löschen, der bei Ausführung die entsprechende Tabellenversion in der Versionierungstabelle erhöht. Wenn Sie erwarten, dass eine der überwachten Tabellen häufig geändert wird, müssen Sie die Wiederverwendung der Version vorsehen. Schließlich fragen Sie in Ihrer Anwendung jedes Mal, wenn Sie eine überwachte Tabelle abfragen, auch deren Version ab und speichern sie. Wenn Sie die überwachte Tabelle in Ihrer App ändern, fragen Sie zuerst die aktuelle Version ab und verarbeiten die Änderung nur, wenn die Version unverändert ist. Sie können proc auf einem SQL Server gespeichert haben, um diese Arbeit für Sie zu erledigen. Dies ist eine extrem einfache, aber bewährte feste Lösung.quelle
Dies ist nicht gerade eine Benachrichtigung, aber im Titel sagen Sie "Monitor" und dies kann zu diesem Szenario passen.
Mithilfe der SQL Server-Zeitstempelspalte können Sie Änderungen (die noch bestehen) zwischen Abfragen leicht erkennen.
Der SQL Server-Zeitstempel-Spaltentyp ist meiner Meinung nach schlecht benannt, da er überhaupt nicht mit der Zeit zusammenhängt. Es handelt sich um einen datenbankweiten Wert, der bei jeder Einfügung oder Aktualisierung automatisch erhöht wird. Sie können Max (Zeitstempel) in einer Tabelle auswählen, nach der Sie suchen, oder den Zeitstempel aus der gerade eingefügten Zeile zurückgeben und dann einfach auswählen, wo Zeitstempel> gespeicherter Zeitstempel angezeigt wird. Dadurch erhalten Sie alle Ergebnisse, die zwischen diesen Zeiten aktualisiert oder eingefügt wurden.
Da es sich auch um einen datenbankweiten Wert handelt, können Sie mit Ihrem gespeicherten Zeitstempel überprüfen, ob in eine Tabelle Daten geschrieben wurden, seit Sie Ihren gespeicherten Zeitstempel zuletzt überprüft / aktualisiert haben.
quelle