#tsql #entity-framework #sql-server-2008
#tsql #entity-framework #sql-server-2008
Вопрос:
Я использую Entity Framework и MSSQL…
Мне нужно вставить пользовательский ссылочный номер при вставке записи. Формат — YYYY-01
, YYYY-02
и т.д., Но порядковый номер необходимо сбросить, когда начнется новый год.
Например 2011-01
, 2011-02
, 2012-01
Мне любопытно, должен ли я просто использовать триггер или управлять этим с помощью EF или?
Сброс последовательной нумерации каждый год меня немного смущает…
Спасибо за любой совет!
Обновить:
Извините, не удалось заставить Code
тег хорошо работать с разметкой
—Переменные
ОБЪЯВИТЕ @year INT,
@seqNum INT;
—Попробуйте выяснить, содержит ли таблица [ComplaintCount] уже текущий год
УСТАНОВИТЕ @year = (ВЫБЕРИТЕ [Count_Year]
Из [Количество жалоб]
, ГДЕ [Count_Year] = ГОД(Getdate()))
—Если текущий год не может быть найден в таблице [Количество жалоб], необходимо создать новую запись за текущий год
ЕСЛИ @year РАВНО НУЛЮ
, НАЧНИТЕ
—Получите текущий год и задайте начальный порядковый номер, чтобы начать отсчет для нового года
SET @year = ГОД(Getdate());
SET @seqNum = 1;
—Вставьте новые значения по умолчанию в таблицу [Количество жалоб]
ВСТАВИТЬ В [Количество жалоб]
(count_year,
count_current)
ЗНАЧЕНИЯ (@year,
@seqNum);
КОНЕЦ
, ДРУГОЕ
НАЧАЛО
— Мы уже нашли запись в таблице [Количество жалоб] за текущий год
— Получаем порядковый номер и увеличиваем его на единицу
УСТАНОВИТЕ @seqNum = (ВЫБЕРИТЕ [Count_Current]
Из [ComplaintCount]
ГДЕ [Count_Year] = @year) 1
—Вставьте новые значения в таблицу [Количество жалоб]
ОБНОВИТЬ [Количество жалоб]
УСТАНОВИТЬ [Count_Current] = @seqNum
ГДЕ [Count_Year] = @year;
КОНЕЦ
— Теперь безопасно вставлять правильный ссылочный номер в таблицу [Жалоба]
ОБНОВИТЬ ОБНОВИТЬ [жалобу]
УСТАНОВИТЬ [Complaint_Reference] = ПРИВЕДЕНИЕ(@year КАК VARCHAR) ‘-‘ ПРИВЕДЕНИЕ(
@seqNum КАК VARCHAR)
ИЗ [Жалобы]
ВНУТРЕННЕГО СОЕДИНЕНИЯ, вставленного
В [жалобу].[PK_Complaint_Id] = вставлено.[PK_Complaint_Id]
Комментарии:
1. Сколько записей в год вы ожидаете? (примерно)
2. Вероятно, около 2 тыс. Я работаю над триггером для управления ссылочным номером, но, похоже, это ужасный способ сделать это.
3. Выберите CreatedYear ‘-‘ (IdField — ISNull((ВЫБЕРИТЕ MIN (IdField) Из базы данных, ГДЕ db.CreatedYear = созданный год), 0) 1)
4. Проблема с этим заключается в том, что идентификатор не сбрасывается в начале каждого нового года. Вы могли бы добавить больше математики для вычисления разницы, но не без необходимости подсчитывать записи при каждой вставке, что вызвало бы много накладных расходов.
Ответ №1:
Я бы сказал, триггер. Создайте таблицу из двух столбцов, в которой хранятся год и номер текущей записи, а затем используйте триггер для поиска текущего года, увеличьте столбец count на единицу, затем верните это количество триггеру. Встроить логику в триггер, согласно которой, если новый год не существует, вставьте запись нового года. Я знаю, что большинству людей нравится избегать триггеров, если это возможно, но это довольно законное использование триггера и намного меньше обработки, чем попытка подсчитать записи при каждой вставке.
Наличие одной строки для каждого года и связанного с ней количества также может оказаться полезным в будущем, когда вы пытаетесь провести аудит за прошлый год или ответить на вопросы BI.
Комментарии:
1. Можете ли вы расширить свой ответ? Это простая часть, но как насчет атомарности, создания последовательности без пробелов, автоматического добавления нового года и т.д.?
2. Добавление нового года так же просто, как проверка и добавление, если у года, который вы пытаетесь увеличить, нет записи. Атомарность? я не думаю, что движок sql сможет справиться с этим, имея всего 2 тыс. вставок в год. Пробелы? Если запись содержит ошибку или удалена пользователем… там будет пробел … ничем не отличающийся от автоматически сгенерированного последовательного ключа, выданного движком.
3. Итак, вы говорите, что если что-то плохое, скорее всего, не произойдет, вам не нужно предотвращать это в вашем коде? Если две параллельные операции запрашивают идентификатор из последовательности, вы можете вставить дубликат номера. Если две параллельные операции создают новый год, у вас будет две последовательности. Если есть требование к последовательности без пробелов, ошибка также должна отменить изменения в последовательности. 2k выглядят не так много, но это также может быть 20×100 записей при асинхронной пакетной обработке. Это требует гораздо большего, чем создание таблицы и триггер.
4. Поскольку вы обновляете приращение одновременно с возвратом значения, вы автоматически получаете гарантию того, что транзакция была «атомарной», поскольку для обновления должна произойти блокировка. Что касается пробелов, если это требование, то вы правы, для этого потребуется намного больше кода.
5. Из вопроса у меня не возникло ощущения, что он искал кого-то, кто написал бы триггер для него. Просто совет о том, есть ли способ получше. Мой ответ был таков: триггер является законным в этом сценарии использования.