Entity Framework 4.2, Невозможно установить Identity Insert ON
Я хотел бы добавить записи в массив в таблицу с заданным идентификатором, чтобы я мог построить иерархию для отображения записей в режиме древовидной структуры. Я могу отдельно добавлять записи, которые отлично работают, и я не устанавливаю ID. Я хотел бы установить идентификаторы только навалом, поэтому я устанавливаю DatabaseGenerated
Option как None
в столбце id для моего объекта как None
.
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
foreach (ErrorCode ec in errorCodesStep3.errorcodesUsers)
{
errorCode.ID = ec.ID;
errorCode.ParentID = ec.ParentID;
errorCode.ErrorDescription = ec.ErrorDescription;
db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.ErrorCode ON");
db.ErrorCode.Add(errorCode);
db.SaveChanges();
scope.Complete();
}
}
ErrorCode
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ID { get; set; }
Я получаю сообщение об ошибке:
не может установить идентификатор, когда вставка идентификатора выключена.
Не уверен, что случилось, так как я видел примеры того, что вставка идентификатора может быть включена. Я использую EF Version 4.2.0.0 и Runtime Version v4.0.30319. Я могу легко добавить инструкцию INSERT через executeSQL
с параметризованными переменными, но я хотел бы сделать это с помощью сущности framework. Похоже, что db.Database.ExecuteSqlCommand
находится в отдельной области действия и закрывается сразу и недоступен, когда выполняется db.savechanged
.
Ответы
Ответ 1
Попробуйте следующее: Entity Framework с вставкой Identity
Возможно так:
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
using (var db = new Context()) // your Context
{
db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.ErrorCode ON");
ErrorCode errorCode = db.ErrorCode.First(); // for example
foreach (ErrorCode ec in errorCodesStep3.errorcodesUsers)
{
errorCode.ID = ec.ID;
errorCode.ParentID = ec.ParentID;
errorCode.ErrorDescription = ec.ErrorDescription;
db.ErrorCode.Add(errorCode);
}
db.SaveChanges();
db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.ErrorCode OFF");
scope.Complete();
}
}
Ответ 2
У меня возникла та же проблема: у нас была таблица, в которой была установлена личность.
то нам нужно было переключить идентификатор на false (я имею в виду сделать это следующим образом)
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ID { get; set; }
но это не сработало после миграции и обновления базы данных.
после того, как я столкнулся с проблемой, я основал эту статью
что означает, что идентификация включения/выключения включения не является прямой, и теперь она не поддерживается платформой Entity Framework.
поэтому решение (которое работало для меня) было следующим
в Visual Studio откройте таблицу в представлении конструктора и выберите столбец, представляющий первичный ключ (который в вашем случае "ID" ), затем из панели свойств найдите свойство "Спецификация идентификатора" (он должен иметь значение true) устанавливает значение false,
и не забудьте обновить таблицу, нажав кнопку "Обновить", чтобы выполнить оператор SQL в таблице. (кнопка обновления существует на панели инструментов таблицы)
затем попробуйте запустить код, он должен работать.
Я надеюсь, что это будет полезно. если у вас есть какие-либо вопросы, пожалуйста, дайте мне знать.
Ответ 3
Вот код, который я проверил, делает то, что вы хотите. Идея состоит в том, чтобы использовать одно соединение как для ExecuteSqlCommand, так и для операций вставки, и кажется, что вызов BeginTransaction() делает трюк:
using (var db = new TestEntities()) {
using (var tran = db.Database.BeginTransaction()) {
db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.Error ON");
foreach (var id in Enumerable.Range(1, 20)) {
var ec = new Error();
ec.ErrorID = id;
db.Errors.Add(ec);
}
db.SaveChanges();
db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.Error OFF");
tran.Commit();
}
}
}
Ответ 4
Добавьте другой столбец для управления иерархией. Столбец идентификатора не должен использоваться для этой цели.
Извините, что не ответил на вопрос, но я не думаю, что ваше решение правильно.