Как отслеживать изменения таблицы SQL Server с помощью c#?
У меня есть несколько приложений, обращающихся к одной и той же БД, и мне нужно получить уведомление, если одно из этих приложений что-либо изменит (обновить, вставить) в определенной таблице.
база данных и приложения не находятся на одном сервере.
9 ответов:
можно использовать
SqlDependency Class. Свое предназначенное использование главным образом для ASP.NET страницы (низкое количество клиентских уведомлений).ALTER DATABASE UrDb SET ENABLE_BROKERреализовать
OnChangeсобытие, чтобы получить уведомление:void OnChange(object sender, SqlNotificationEventArgs e)и в коде:
SqlCommand cmd = ... cmd.Notification = null; SqlDependency dependency = new SqlDependency(cmd); dependency.OnChange += OnChange;использует
Service Broker(коммуникационная платформа на основе сообщений) для получения сообщений от компонента Database engine.
Как правило, нужно использовать Service Broker
это триггер - > очередь - > приложение(ы)
редактировать, увидев другие ответы:
FYI: "уведомления о запросах" построен на Service broker
Edit2:
в интересах полноты есть несколько других решений, которые, на мой взгляд, более ортодоксальны и хорошо зарекомендовали себя, чем решения, основанные на классах SqlDependency (и SqlTableDependency). SqlDependency был разработан для обновления Кэша веб-сервера, и поэтому на самом деле не обеспечивает такую устойчивость под нагрузкой, которая требуется от производителя событий.
есть в целом четыре других варианта, которые еще не упомянуты здесь:
- Отслеживание Изменений
- CDC
- триггеры очереди
- CLR
отслеживание изменений
отслеживание изменений-это легкий механизм уведомления в SQL server. В принципе, номер версии для всей базы данных увеличивается с каждым изменением любые данные. Номер версии затем записывается в таблицы отслеживания изменений с битовой маской, включающей имена столбцов, которые были изменены. Обратите внимание, что фактическое изменение не сохраняется. Уведомление содержит только информацию об изменении конкретного объекта данных. Кроме того, поскольку управление версиями таблицы изменений является кумулятивным, отдельные изменения не сохраняются и перезаписываются новыми изменениями. Это означает, что если объект изменяется дважды, отслеживание изменений будет знать только о самое последнее изменение.
чтобы зафиксировать эти изменения в c#, необходимо использовать опрос. Таблицы изменений могут быть опрошены и каждое изменение проверено, чтобы увидеть, если представляет интерес. Если это представляет интерес, необходимо затем перейти непосредственно к данным, чтобы получить текущее состояние.
Изменить Сбор Данных
источник:https://technet.microsoft.com/en-us/library/bb522489 (v=sql. 105). aspx
система отслеживания измененных данных (CDC с) является более мощным, но наиболее дорогостоящим, чем отслеживание изменений. Система отслеживания измененных данных будет отслеживать и уведомлять об изменениях на основе мониторинга журнала базы данных. Из-за этого CDC имеет доступ к фактическим данным, которые были изменены, и ведет учет всех индивидуальных изменений.
аналогично отслеживанию изменений, чтобы зафиксировать эти изменения в c#, необходимо использовать опрос. Однако в случае CDC опрошенная информация будет содержать детали изменения, поэтому строго не нужно идти вернемся к самим данным.
триггеры очереди
источник:https://code.msdn.microsoft.com/Service-Broker-Message-e81c4316
этот метод зависит от триггеров в таблицах, от которых требуются уведомления. Каждое изменение запускает триггер, и триггер записывает эти сведения в очередь компонента Service broker. Затем очередь может быть подключена через C# с помощью обработчика сообщений компонента Service Broker (пример в разделе ссылка выше).
В отличие от отслеживания изменений или CDC, триггеры для очередей не полагаются на опрос и тем самым обеспечивают событие в реальном времени.
CLR
этот метод я видел, но я бы не советовал. Любое решение, которое полагается на CLR для внешнего общения, в лучшем случае является взломом. Среда CLR была разработана для упрощения написания сложного кода обработки данных с использованием C#. Он не был разработан для подключения во внешних зависимостях, таких как библиотеки обмена сообщениями. Кроме того, связанные операции среды CLR могут нарушаться в кластерных средах непредсказуемым образом.
тем не менее, это довольно просто настроить, так как все, что вам нужно сделать, это зарегистрировать сборку сообщений с помощью среды CLR, а затем вы можете вызвать с помощью триггеров или заданий SQL.
в резюме...
для меня всегда было источником удивления, что Microsoft упорно отказывалась решать эту проблему пространства. Троеборье от базы данных к коду должна быть встроена функция продукта базы данных. Учитывая, что Oracle Advanced Queuing в сочетании с ODP.net MessageAvailable событие обеспечило надежную базу данных eventing на C# больше, чем 10 лет назад, это прискорбно от госпожи
результатом этого является то, что ни одно из решений, перечисленных в этом вопросе, не очень приятно. Все они имеют технические недостатки и имеют значительную стоимость установки. Microsoft, если вы слушаете, пожалуйста, разберитесь в этом плачевном положении дел.
Использовать SqlTableDependency. Это компонент c#, вызывающий события при изменении записи. Вы можете найти другие детали по адресу: https://github.com/christiandelbianco/monitor-table-change-with-sqltabledependency
это похоже на .NET SqlDependency за исключением того, что sqltabledependency вызывает события, содержащие измененные / удаленные или обновленные значения таблицы базы данных:
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); } }
объект sqldependency не смотреть в базе он смотрит sqlcommand, который вы укажите, поэтому если вы пытаетесь допустим, вставки значений в базу данных в 1 проект и запечатлеть это событие в другом проекте это не работает, потому что мероприятие было с sqlcommand, который от 1º проект не база данных, потому что когда вы создаете экземпляр sqldependency вы связать его с sqlcommand и только тогда, когда эта команда из этого проекта используется ли создать событие изменения.
с SQL Server 2005 у вас есть возможность использовать Уведомления О Запросах, которое может быть использовано мимо ADO.NET см. http://msdn.microsoft.com/en-us/library/t9x04ed2.aspx
будьте осторожны при использовании SqlDependency класс - это проблемы с утечками памяти. Однако вы можете использовать свою собственную реализацию с триггерами DDL и SQL Service Broker API или использовать один из проектов с открытым исходным кодом, например,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);надеюсь, что это помогает.
похоже, что плохая архитектура полностью. также вы не указали тип приложения, которое вам нужно уведомить (веб-приложение / консольное приложение / winforms / service и т. д.)
тем не менее, отвечая на ваш вопрос, есть несколько способов решения этой. вы могли бы использовать:
1), Если вы просто заинтересованы в обеспечении следующего набора обновлений от второго приложения не конфликтуют с обновлениями от первого приложения
2) объект зависимости sql-см. http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldependency.aspx для получения дополнительной информации
3) пользовательская служба push-уведомлений, на которую могут подписаться несколько клиентов (web / winform / service) и получать уведомления об изменениях
короче говоря, вам нужно использовать самое простое и простое и дешевое (с точки зрения усилий) решение, основанное на том, насколько сложны ваши требования к уведомлению и для какой цели вам нужно их использовать. не пытайтесь построить чрезмерно сложная система уведомлений если простой параллелизм данных является вашим единственным требованием (в этом случае перейдите на простое решение на основе временных меток)
другой, очень простой способ мониторинга таблиц-это управление версиями таблиц. Доказано, что система работает в таких конструкциях, как синхронизация DNS. Чтобы заставить его работать, вы создаете таблицу, содержащую имена таблиц и версии таблиц как
decimalилиbigint.в каждой таблице, которую вам нужно отслеживать, создайте триггер на insert, update и delete, который увеличит соответствующую версию таблицы в таблице управления версиями при выполнении. Если вы ожидаете, что какая-либо из отслеживаемых таблиц будет часто изменяться, вам необходимо предоставление для повторного использования версии. Наконец, в вашем приложении каждый раз, когда вы запрашиваете отслеживаемую таблицу, вы также запрашиваете ее версию и сохраняете ее. Когда вы переходите к изменению отслеживаемой таблицы из вашего приложения, вы сначала запрашиваете ее текущую версию и обрабатываете изменение только в том случае, если версия не изменилась. Вы можете сохранить proc на sql server сделать эту работу за вас. Это чрезвычайно простое, но проверенное твердое решение. Оно имеет специфическое функциональное использование (для обеспечения целостности данных) и ресурсов (вы не поднимайте посреднические события, которые вы не будете наблюдать), но приложение должно активно проверять изменения, а не пассивно ждать события.
Comments