Так что, держу пари, я заинтересовался этим названием.=)
Вот сценарий - упрощенный по причине.
Website: ASP.NET 4 Web Forms.
Database: SQL Server 2008.
DAL: LINQ-SQL.
В БД у нас есть две таблицы: Foo
и Bar
.
Отношение 1-1
, а Bar
имеет ограничение внешнего ключа Foo
.Другими словами, вам нужно сначала создать Foo
, а затем использовать PK для Foo
при создании Bar
.Две таблицы объединяются, чтобы создать бизнес-сущность с именем FooBar
.
Теперь у нас есть система скоринга для нашего веб-сайта.Некоторые действия приводят к необходимости обновления оценки для определенных FooBar
.
. В настоящее время у нас есть триггеры как для таблиц Foo
, так и Bar
.Оба триггера вызывают хранимую процедуру, которая обновляет оценки для конкретного FooBar
.
Так что в этом заключается проблема - мы создаем новый FooBar
на веб-сайте, который вызывает записи в Foo
и Bar
быть созданным.Оба триггера срабатывают (сначала Foo
, затем Bar
), и одна и та же хранимая процедура выполняется дважды.Не наносит никакого реального вреда, просто не приносит пользы.
Как мы можем обойти это?
Хранимая процедура, которая обновляет оценки для FooBar
, проста - принимает FooID
.
Мы не можемвыполнять оценку до тех пор, пока не будет создана запись в Bar
.Несмотря на то, что в настоящее время это происходит для триггера Foo
, счет оказывается неверным до тех пор, пока он не будет переделан на триггер Bar
.Также следует отметить, что выполнение каких-либо действий на веб-сайте может не повлиять на ОБА таблицы (т.е. вы можете отредактировать FooBar
на сайте и в конечном итоге изменить только таблицу Foo
или только таблицу Bar
, в других случаяхоба).
Триггеры: AFTER INSERT, UPDATE or DELETE
.
Вот что я имею в виду для трех возможных сценариев:
Пользователь создает новый FooBar:
- В Foo добавлена новая запись
- Триггер выполнен на Foo
- Выполнен подсчет очков SP
- FooBar неправильно оценен (потому что пока нет бара)
- Новая запись добавлена к бару
- Триггер выполнен на такте
- Скоринг SP выполнен
- FooBar правильно набрал
Пользователь редактирует "Foo" для FooBar:
- Обновлена запись Foo.
- Триггер выполнен на Foo
- Скоринг SP выполнен
- FooBarЗабил правильно.
Пользователь редактирует "Бар" для FooBar:
- Обновлена запись бара.
- Триггер выполнен на полосе
- Scoring SP Выполнен
- FooBar оценен правильно.
Так что сценарии 2 и 3 хороши - это при добавлении новыхFooBar, который вызывает проблему.
Вот мои идеи на данный момент:
Удалите триггеры из Foo
и Bar
.Создание асинхронного вызова потока в C # после успешного создания записей таблицы Foo
и Bar
(т. Е. После успешного выполнения операций LINQ
), вызывающих хранимую процедуру.Проблема в том, что, во-первых, я всегда стараюсь избегать многопоточности на веб-сайтах, если это абсолютно не требуется, более того, добавление зависимости к веб-серверу, когда фактически вся эта логика и владелец должны быть (и в настоящее время есть) в базе данных.
Создайте «промежуточную» таблицу, триггеры создадут запись в промежуточной таблице (что-то вроде "FooID1", "ReadyToScore"
- например).Затем задание SQL будет опрашивать эту таблицу (скажем, каждые 30 секунд) и выполнять хранимую процедуру.Очевидные проблемы с этим - дополнительная нагрузка из-за опроса и большая трудность для отладки.
Трудный вопрос для понимания, я знаю, так что, надеюсь, я все объяснил хорошо.
Есть мысли?