Нам всегда нравилось использовать последовательность в базах данных Oracle для создания глобально уникальных идентификаторов первичных ключей для всей базы данных. Настолько, что мы будем имитировать то же самое при использовании баз данных SQL Server:
CREATE TABLE MainSequence(
Id int IDENTITY(1,1) CONSTRAINT pkMainSequence PRIMARY KEY
)
Я пытаюсь перейти на Entity Framework, который для меня очень новый. Казалось, что было бы тривиально создать метод расширения, который я мог бы использовать, чтобы быстро получить следующий доступный глобально уникальный идентификатор.
public static int GetNextId( this Entities db ) {
var ms = new MainSequence();
db.MainSequences.AddObject( ms );
db.SaveChanges( SaveOptions.None );
return ms.Id;
}
Поскольку это столбец идентификаторов, все, что мне нужно сделать, это добавить новый объект в базу данных и сохранить изменения, чтобы свойство Id было обновлено с реальным значением. Это отлично работает. Но, похоже, у меня возникают проблемы при попытке использовать его для таблиц, связанных с внешними ключами:
var dataId = db.GetNextId();
db.Datas.AddObject( Data.CreateData( dataId, someValueForThisColumn );
db.Caches.AddObject(
Cache.CreateCache( db.GetNextId(),
DatabaseMethods.GetOrAddLocation( source.GetLocationText() ),
DateTime.Now,
dataId ) );
Таблица Cache имеет внешний ключ для таблицы данных. Когда SaveChanges();
вызывается сразу после этого, генерируется исключение.
System.Data.SqlClient.SqlException: нарушение ограничения PRIMARY KEY 'pkData'. Невозможно вставить дубликат ключа в объект 'dbo.Data'. Значение дубликата ключа (78162).
Заявление было прекращено.
Почему-то кажется, что новую строку данных пытаются вставить в базу данных дважды, хотя я не уверен, почему это так. Я подтвердил, что при каждом запуске кода возвращается другой идентификатор MainSequence. Кажется, что вызов db.SaveChanges
всякий раз, когда получается новый идентификатор, является проблемой, но нет другого способа, которым можно заполнить реальный int
, и я не понимаю, почему это будет проблемой. Что я делаю не так?