#sql-server #entity-framework-core
#sql-сервер #entity-framework-core
Вопрос:
При работе с SQL Server (через Entity Framework Core 3) и иметь требование добавлять участников в группу, но с ограничением количества участников, разрешенных в каждой группе. Я проиллюстрирую:
Структура таблицы:
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[MemberId] [bigint] NOT NULL,
[GroupNumber] [bigint] NOT NULL,
[PositionInGroup] [int] NOT NULL
Каждый раз, когда я добавляю новую строку в эту таблицу, мне нужно вычислить «GroupNumber» и «PositionInGroup» для нового члена. В каждом «GroupNumber» может быть только 5 элементов.
Итак, при добавлении новой записи мне нужно…
- Получить наибольшее значение для номера «GroupNumber»
- Подсчитайте количество людей в GroupNumber
- Увеличьте PositionInGroup в GroupNumber и перенесите на «0», если больше 5 (максимально допустимый в группе)
- Если позиция в группе равна нулю (т. Е. Мы перевернулись), увеличьте GroupNumber на 1
- Создайте новую запись со значением GroupNumbernumber и PositionInGroup
Поскольку существует ряд вычислений, которые должны выполняться на основе строк в таблице, каков наилучший способ управлять этим в SQL Server (или EF Core Framework), чтобы предотвратить присвоение членам неправильных / повторяющихся номеров групп / позиций из-за одновременных запросов на добавление группы?
Что лучше всего обрабатывать с помощью транзакций или какой-то атомной вставки? Если это должно обрабатываться с помощью транзакции, какой уровень изоляции является наиболее подходящим?
Если это имеет значение, я ожидаю не более 500 таких вызовов в течение 12-часового периода, поэтому я не очень беспокоюсь о конфликте блокировок — я забочусь в первую очередь о целостности данных.
Вот как я ожидаю, что данные будут выглядеть после 15 вставок. Обратите внимание, что счетчик «PositionInGroup» сбрасывается после достижения максимального значения PositionInGroup, равного 5.
Член может находиться только в одной группе в одной позиции. Как только член находится в группе на определенной позиции, он никогда не может измениться. Элемент будет добавлен в эту таблицу только один раз.
Заранее спасибо.
Комментарии:
1. Показать некоторые примеры данных и ожидаемые результаты. Очень сложно разобраться в чтении такого большого количества текста.
2. Может ли участник входить более чем в 1 группу?
3. Нет. Член может находиться только в одной группе и в одной позиции.
Ответ №1:
Интересное упражнение. Я бы выбрал вычисляемые столбцы для обеспечения полной целостности.
Вы должны связать фактического пользователя или что-то еще в качестве внешнего ключа в этой таблице, поскольку жизненно важно, чтобы идентификатор элемента был последовательным.
настройка / ввод
DECLARE @test TABLE (
memberId int identity(1,1),
groupNumber as (memberId - 1) / 5 1
);
insert into @test default values
insert into @test default values
insert into @test default values
insert into @test default values
insert into @test default values
insert into @test default values
insert into @test default values
insert into @test default values
insert into @test default values
insert into @test default values
insert into @test default values
insert into @test default values
insert into @test default values
insert into @test default values
insert into @test default values
select *,
row_number() over (partition by groupNumber order by memberId) as positionInGroup
from @test
order by memberId
вывод
---------- ------------- -----------------
| memberId | groupNumber | positionInGroup |
---------- ------------- -----------------
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 3 |
| 4 | 1 | 4 |
| 5 | 1 | 5 |
| 6 | 2 | 1 |
| 7 | 2 | 2 |
| 8 | 2 | 3 |
| 9 | 2 | 4 |
| 10 | 2 | 5 |
| 11 | 3 | 1 |
| 12 | 3 | 2 |
| 13 | 3 | 3 |
| 14 | 3 | 4 |
| 15 | 3 | 5 |
---------- ------------- -----------------
Комментарии:
1. Спасибо за это! Что, если не обязательно, чтобы идентификатор участника был последовательным? Т. Е. это может быть любой уникальный идентификатор участника. Это что-то меняет?
2. очень важно, чтобы идентификатор элемента был идентификатором (1,1), числовой последовательностью без пробелов, начинающейся с 1, иначе вычисления GroupNumber и positionInGroup завершатся неудачей. но, как я пишу, вы можете добавить любой другой объект, используя внешний ключ в этой таблице.