T-SQL: триггер с двойной связью, опрос или асинхронный поток .NET? - PullRequest
0 голосов
/ 30 июня 2010

Так что, держу пари, я заинтересовался этим названием.=)

Вот сценарий - упрощенный по причине.

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.

Вот что я имею в виду для трех возможных сценариев:

  1. Пользователь создает новый FooBar:

    • В Foo добавлена ​​новая запись
    • Триггер выполнен на Foo
    • Выполнен подсчет очков SP
    • FooBar неправильно оценен (потому что пока нет бара)
    • Новая запись добавлена ​​к бару
    • Триггер выполнен на такте
    • Скоринг SP выполнен
    • FooBar правильно набрал
  2. Пользователь редактирует "Foo" для FooBar:

    • Обновлена ​​запись Foo.
    • Триггер выполнен на Foo
    • Скоринг SP выполнен
    • FooBarЗабил правильно.
  3. Пользователь редактирует "Бар" для FooBar:

    • Обновлена ​​запись бара.
    • Триггер выполнен на полосе
    • Scoring SP Выполнен
    • FooBar оценен правильно.

Так что сценарии 2 и 3 хороши - это при добавлении новыхFooBar, который вызывает проблему.

Вот мои идеи на данный момент:

  1. Удалите триггеры из Foo и Bar.Создание асинхронного вызова потока в C # после успешного создания записей таблицы Foo и Bar (т. Е. После успешного выполнения операций LINQ), вызывающих хранимую процедуру.Проблема в том, что, во-первых, я всегда стараюсь избегать многопоточности на веб-сайтах, если это абсолютно не требуется, более того, добавление зависимости к веб-серверу, когда фактически вся эта логика и владелец должны быть (и в настоящее время есть) в базе данных.

  2. Создайте «промежуточную» таблицу, триггеры создадут запись в промежуточной таблице (что-то вроде "FooID1", "ReadyToScore" - например).Затем задание SQL будет опрашивать эту таблицу (скажем, каждые 30 секунд) и выполнять хранимую процедуру.Очевидные проблемы с этим - дополнительная нагрузка из-за опроса и большая трудность для отладки.

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

Есть мысли?

Ответы [ 2 ]

0 голосов
/ 06 июля 2010

Решено оставить все как есть (выполняется обработка дважды).

Причины: - Сама обработка довольно эффективна (<1 сек).- Опрос, многопоточность, Async T-SQL VS, два 1-секундных вызова.Ежу понятно. </p>

0 голосов
/ 30 июня 2010

Вы также можете рассмотреть Асинхронные процедуры T-SQL , которые устраняют необходимость в объединении заданий и даже в промежуточные таблицы.

...