Поле увеличения в рамках сущности в зависимости от значения другого поля
-
25-10-2019 - |
Вопрос
Я новичок в рамках Entity, и у меня есть проблемы с чем-то, что было довольно легко в Pure T-SQL. Предположим, что у нас есть таблица с 3 столбцами. Id (идентификация, первичный ключ), idkind (int), number (int). Столбец Nubmer зависит от столбца Idkind. Данные в этой таблице должны выглядеть так:
Id | Idkind | Число
1 | 1 | 1
2 | 1 | 2
3 | 1 | 3
4 | 2 | 1
5 | 2 | 2
6 | 2 | 3
Как вы можете видеть, номер столбца является автоматическим увеличением, зависит от idkind. В T-SQL я нашел макс (номер) + 1 для некоторого идентификатора. Все было в одной сохраненной процедуре в одной транзакции, поэтому значение числа было уникальным для Idkind.
Как сделать то же самое в рамках сущности. Значение числа должно быть рассчитано при создании нового объекта или при изменении Idkind.
Решение
Я бы использовал триггер базы данных для этого и настраивал Number
свойство в картировании EF с StoreGeneratedPattern.Computed
сообщить EF, что это свойство заполняется в базе данных и должно быть перезагружено после каждого обновления / вставки.
Я также не использовал бы max () для каждого нового номера. Вместо этого я бы сохранил отдельные таблицы, моделирующие последовательности. Эта таблица должна содержать запись в последовательности - в вашем случае записи на IdKind
с текущим максимальным номером. Вместо того, чтобы выбрать агрегацию, вы выберете одиночную запись и обновите ее, чтобы содержать новый максимальный номер. Работа с этой таблицей должна быть в той же транзакции, что и постоянные изменения в вашей сущности.
Другие советы
У меня была та же проблема, но я решил ее в C#.
У меня должна быть предприятие, нанесенное на таблицу:
public class MyEntity
{
Kind IdKind{get; set;}
int Number{get;set;}
}
У меня должны быть и вспомогательную сущность для хранения последнего числа, используемого для вида.
public class LastNumber
{
Kind IdKind{get;set;}
int LastNumber{get;set;}
}
Затем, прежде чем добавить строку (объект MyEntity) в таблицу, я должен рассчитать правильное число, используя поля LastNumber LastNumberlity с видом, равным моему добрым значению.
Мы должны отметить, что эта стратегия имеет проблему параллелизма, поскольку два разных потока могут добавлять объект одного и того же типа одновременно, эти потоки будут осматривать ту же последнюю точку зрения, чтобы получить последнее значение. Эта проблема имеет известное решение в EntityFramework. Код может выглядеть так:
public int GetNumber(Kind idKind)
{
using (var db = new MyDataContext())
{
var lastNumber = db.LastNumbers.Single(x=>x.IdKind == idKind);
for (int attemps = 0; attemps < 10;)
{
try
{
lastNumber.LastNumber++;
db.SaveChanges();
return lastNumber.LastNumber;
}
catch (DbUpdateConcurrencyException ex)
{
attemps++;
}
}
}
throw new Exception("Many concurrency calls");
}
Этот метод получает постепенное число для указанного вида и обрабатывает проблему параллелизма, используя его, мы можем установить значение номера для каждого объекта MyEntity. Клиентский код может выглядеть так:
var entity = new MyEntity();
var number = GetNumber(entity.IdKind);
entity.Number = number;
db.MyEntities.Add(entity);
db.SaveChanges();
Этот код может быть рефактован, что делает сети частными, создавая завод, чтобы обеспечить создание организаций, используя метод GetNumber и использование репозитории для управления БД.