Intereting Posts
Если hash-код нулевого значения всегда равен нулю, в .NET Является ли приложение связанным с данным расширением? C # из памяти при создании растрового изображения Как определить, выполняется ли программа во время выполнения во время выполнения исключения? Как получить Диспетчер в не-пользовательском коде Windows Phone 8 asp.net mvc razor дополнительное пространство Можно ли программно генерировать сертификат X509, используя только C #? DbSet не имеет метода поиска в EF7 Разделение строки на основе неравномерного количества пробелов Может ли кто-нибудь объяснить «доступ к модифицированному закрытию» на C # простым языком? Изменить цвет выделения WPF ListViewItem Асинхронный метод не ждет Почему ReSharper говорит мне «неявно зафиксированное закрытие»? Как сохранить текст только для чтения TextBox после PostBack ()? Передать значения checkBox в действие controllerа в asp.net mvc4

Как уведомить службу Windows (c #) об изменении таблицы базы данных (sql 2005)?

У меня есть таблица с большой нагрузкой (многие вставки / обновления / удаления) в базе данных SQL2005. Я бы хотел сделать некоторую пост-обработку для всех этих изменений как можно ближе к реальному времени (асинхронно, чтобы не заблокировать таблицу каким-либо образом). Я рассмотрел ряд возможных решений, но просто не могу найти подходящее решение.

Тип почтовой обработки также довольно тяжелый, настолько, что служба прослушивателя окон фактически передаст обработку на несколько машин. Однако эта часть приложения уже запущена, полностью асинхронна, а не нужна мне помощь. Я просто хотел упомянуть об этом просто потому, что это повлияло на конструктивное решение, поскольку мы не могли просто загрузить некоторый объект CLR в DB для завершения обработки.

Итак, простая проблема остается: изменения данных в таблице, я хочу сделать некоторую обработку в коде c # на удаленном сервере.

В настоящее время мы придумали использование SQL-триггера, который выполняет «xp_cmdshell» для lauch exe, который вызывает событие, которое слушает служба Windows. Это просто плохо.

Тем не менее, другие решения, которые я просматривал в Интернете, выглядят довольно запутанными. Например, настройка SQLCacheDependancy также требует установки Service broker. Другим возможным решением является использование триггера CLR, который может вызвать веб-сервис, но в этом так много предупреждений в Интернете о том, что это плохой способ сделать это, особенно когда производительность критическая.

В идеале мы бы не отразились на изменениях в таблице, но предпочли бы перехватить вызов внутри нашего приложения и оповестить службу оттуда, к сожалению, хотя у нас есть некоторые устаревшие приложения, вносящие изменения в данные, и мониторинг таблицы является единственным централизованным местом в момент.

Любая помощь будет оценена по достоинству.

Резюме:

  • Необходимо реагировать на изменения табличных данных в реальном времени
  • Производительность критическая
  • Ожидается большой объем трафика
  • Опрос и запланированные задачи не являются опцией (или в режиме реального времени)
  • Реализация сервис-брокера слишком велика (но может быть только решение?)
  • Код CLR еще не исключен, но должен быть выполнен, если предлагается
  • Слушателем / монитором может быть удаленная машина (вероятно, такая же физическая сеть)

    У вас действительно нет таких способов обнаружения изменений в SQL 2005. Вы уже указали большинство из них.

    Уведомления о запросах . Это технология, которая управляет SqlDependency и ее производными, вы можете прочитать более подробную информацию о The Mysterious Notification . Но QN предназначен для недействительности результатов, а не для активного уведомления о содержании изменений. Вы только знаете, что таблица имеет изменения, не зная, что изменилось. В занятой системе это не сработает, так как уведомления будут поступать довольно долго.

    Чтение журнала . Это то, что использует транзакционная репликация, и является наименее интрузивным способом обнаружения изменений. К сожалению, доступно только для внутренних компонентов. Даже если вам удастся понять формат журнала, проблема в том, что вам нужна поддержка от механизма, чтобы пометить журнал как «используемый», пока вы его не прочитаете, или он может быть перезаписан. Только транзакционная репликация может выполнять такую ​​специальную маркировку.

    Сравнение данных . Положитесь на столбцы timestamp для обнаружения изменений. Является также натягивающим, довольно интрузивным и имеет проблемы с обнаружением удалений.

    Уровень приложения . Это лучший вариант в теории, если только изменения не происходят за пределами данных приложения, и в этом случае он рушится. На практике всегда происходят изменения вне сферы применения приложения.

    Триггеры . В конечном счете, это единственный жизнеспособный вариант. Все механизмы изменения, основанные на триггерах, работают одинаково, они приостанавливают уведомление об изменении компоненту, который контролирует очередь.

    Всегда есть предложения по строгому синхронному уведомлению (через xp_cmdshell, xp_olecreate, CLR, уведомлять с WCF, вы называете это), но все эти схемы не работают на практике, потому что они в корне ошибочны:
    – они не учитывают согласованность транзакций и откаты
    – они устанавливают зависимости доступности (система OLTP не может действовать, если только уведомленный компонент не подключен)
    – они выполняются ужасно, так как каждая операция DML должна дождаться вызова RPC какой-либо формы для завершения

    Если триггеры на самом деле не активно уведомляют слушателей, но только в очереди на уведомления, есть проблема в мониторинге очереди уведомлений (когда я говорю «очередь», я имею в виду любую таблицу, которая действует как очередь). Мониторинг предполагает вытягивание новых записей в очереди, что означает правильную балансировку частоты проверок с нагрузкой изменений и реагирование на нагрузки. Это совсем не тривиально, на самом деле это очень сложно. Однако на SQL-сервере есть один оператор, который имеет семантику для блокировки, без вытягивания, до тех пор, пока не станут доступны изменения: WAITFOR (RECEIVE) . Это означает Service Broker. Вы упомянули SSB несколько раз в своем посте, но вы, верно, боитесь развернуть его из-за большого неизвестного. Но реальность такова, что она, безусловно, лучше всего подходит для описанной вами задачи.

    Вам не нужно развертывать полную архитектуру SSB, где уведомление доставляется до удаленного сервиса (для чего требуется удаленный экземпляр SQL, даже Express). Все, что вам нужно сделать, это отделить момент, когда обнаружение изменения (триггер DML) с момента подачи уведомления (после того, как изменение выполнено). Для этого вам нужна только локальная SSB-очередь и служба. В триггере вы отправляете уведомление об изменении в локальную службу. После совершения первоначальной транзакции DML процедура обслуживания активирует и отправляет уведомление, используя, например, CLR. Вы можете увидеть пример чего-то подобного в Asynchronous T-SQL .

    Если вы спуститесь по этому пути, вам понадобятся некоторые трюки, необходимые для достижения высокой пропускной способности, и вы должны понимать концепцию упорядоченной доставки сообщений в SSB. Я рекомендую вам прочитать эти ссылки:

    • Повторное использование разговоров
    • Написание процедур брокерских услуг
    • Демо-версия SQL Connections 2007

    О средствах обнаружения изменений, SQL 2008, по- видимому, добавляет новые параметры: изменение захвата данных и отслеживание изменений . Я подчеркиваю «по-видимому», поскольку они не являются новыми технологиями. CDC использует программу чтения журналов и основывается на существующих механизмах репликации транзакций. CT использует триггеры и очень похож на существующие механизмы репликации Merge. Они оба предназначены для периодически подключаемых систем, которые необходимо синхронизировать и, следовательно, не подходят для уведомления об изменении в режиме реального времени. Они могут заполнять таблицы изменений, но у вас остается задача отслеживать эти таблицы для изменений, которые точно от того, с чего вы начали.

    Это можно сделать разными способами. ниже метод прост, так как вы не хотите использовать триггеры CLR и sqlcmd.

    • Вместо использования триггеров CLR вы можете создать обычный триггер insert, который обновляет выделенную таблицу отслеживания для каждой вставки.

    • И создайте специализированный оконный сервис, который активно обследует таблицу отслеживания и обновляет удаленную службу, если есть какие-либо изменения в данных и задан статус в таблице отслеживания (поэтому его больше не будет выбрано).

    РЕДАКТИРОВАТЬ:

    Я думаю, что службы синхронизации Microsoft для ADO.Net могут работать на вас. Ознакомьтесь с приведенными ниже ссылками. Это может помочь вам

    • Практическое руководство. Использование отслеживания изменений SQL Server – сервер SQL Server 2008
    • Использование пользовательской системы отслеживания изменений – ниже sql server 2008

    В подобных обстоятельствах мы используем триггер CLR, который записывает сообщения в очередь (MSMQ). Служба, написанная на C #, контролирует очередь и выполняет пост-обработку. В нашем случае все делается на одном сервере, но вы можете отправлять эти сообщения непосредственно в удаленную очередь на другой машине, полностью обходя «локальный слушатель».

    Код, вызываемый из триггера, выглядит следующим образом:

    public static void SendMsmqMessage(string queueName, string data) { //Define the queue path based on the input parameter. string QueuePath = String.Format(".\\private$\\{0}", queueName); try { if (!MessageQueue.Exists(QueuePath)) MessageQueue.Create(QueuePath); //Open the queue with the Send access mode MessageQueue MSMQueue = new MessageQueue(QueuePath, QueueAccessMode.Send); //Define the queue message formatting and create message BinaryMessageFormatter MessageFormatter = new BinaryMessageFormatter(); Message MSMQMessage = new Message(data, MessageFormatter); MSMQueue.Send(MSMQMessage); } catch (Exception x) { // async logging: gotta return from the trigger ASAP System.Threading.ThreadPool.QueueUserWorkItem(new WaitCallback(LogException), x); } } 

    Поскольку вы сказали, что на этом столе работает много вложений, пакетная обработка может поместиться лучше.

    Почему просто создайте запланированное задание, которое обрабатывает новые данные, идентифицированные столбцом флага, и обрабатывает данные в больших кусках?

    Используйте обычный триггер для запуска CLR в базе данных. Эта среда CLR запускает удаленную программу только с помощью classа Win32_Process:

    http://motevich.blogspot.com/2007/11/execute-program-on-remote-computer.html