Могут ли триггеры SQL CLR сделать это? Или есть лучший способ?
Я хочу написать сервис (вероятно, в C#), который контролирует таблицу базы данных. Когда запись вставляется в таблицу, я хочу, чтобы сервис захватывал вновь вставленные данные и выполнял с ними некоторую сложную бизнес-логику (слишком сложную для TSQL).
Один из вариантов заключается в том, чтобы служба периодически проверяла таблицу на предмет наличия новых записей. Проблема с этим заключается в том, что я хочу, чтобы служба знала о вставках, как только они происходят, и я не хочу снижать производительность базы данных.
Делая небольшое исследование, кажется, что, возможно, написание триггера CLR может сделать эту работу. Я мог бы написать триггер в C#, который срабатывает при вставке, а затем отправить вновь вставленные данные в службу Windows или WCF.
Как вы думаете, это хорошее (или даже возможное) использование триггеров SQL CLR?
Любые другие идеи о том, как это сделать?
6 ответов
Вероятно, вы должны отсоединить постобработку от вставки:
В триггере "Вставка" добавьте PK записи в таблицу очередей.
В отдельном сервисе прочитайте из таблицы очередей и выполните сложную операцию. По окончании пометьте запись как обработанную (вместе с информацией об ошибке / состоянии) или удалите запись из очереди.
То, что вы описываете, иногда называют очередью заданий или очередью сообщений. Существует несколько потоков об использовании таблицы СУБД (а также других методов) для этого, которую вы можете найти, выполнив поиск.
Я бы посоветовал сделать что-либо подобное с помощью Trigger как ненадлежащее использование функции базы данных, с которой в любом случае легко попасть в неприятности. Триггеры лучше всего использовать для структурной функциональности dbms с низкими издержками (например, детальной проверки ссылочной целостности) и должны быть легкими и синхронными. Это может быть сделано, но, вероятно, не будет хорошей идеей.
Я предложил бы иметь в таблице триггер, который вызывает SQL Server Service Broker, который затем (асинхронно) выполняет хранимую процедуру CLR, которая выполняет всю вашу работу в другом потоке.
У меня есть служба, которая опрашивает базу данных каждую минуту, она не вызывает особых проблем с производительностью и является чистым решением. Кроме того, если вашей службы или другой конечной точки wcf нет, ваш триггер не будет работать или будет потерян, и вам придется в любом случае опрашивать позже.
Я бы не рекомендовал использовать триггер CLR или какой-либо другой триггер для этого. Вы открываете себя серьезной ремонтопригодности и потенциальным проблемам с блокировкой. (Очень простой триггер, который забирает вещи в таблицу аудита / очереди, может быть приемлемым, если вы не заботитесь о @@identity после вставок и никогда не заблокируете таблицу аудита / очереди)
Вместо этого из вашего приложения /orm вы должны инициировать вставку содержимого в таблицу очередей и регулярно обрабатывать эту очередь. Это можно сделать, запустив транзакцию в вашем ORM или запустив сохраненный процесс, когда транзакция запускает изменение и аудит / очередь атомарно. (будьте осторожны с блокировкой здесь)
Если вам нужны немедленные действия, посмотрите на порождение задания, чтобы очистить очередь после того, как вы выполните вставку / обновление / удаление таблицы и
Также убедитесь, что вы дважды проверяете очередь раз в минуту или около того, если фоновый процесс не был запущен должным образом. Если это веб-приложение и вы хотите избежать порождения потоков, вы можете связаться с фоновым процессом, чтобы очистить очередь.
Почему бы не внедрить вставку в хранимую процедуру, а выполнить бизнес-логику в процедуре после вставки? Что в этом такого сложного, что его нельзя написать на T-SQL?