Поле увеличения в рамках сущности в зависимости от значения другого поля

StackOverflow https://stackoverflow.com/questions/8309088

  •  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 и использование репозитории для управления БД.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top