Проблема столбца идентификатора EF Core database-first

Я использую EF Core 3.1 с подходом сначала к базе данных, используя Linq-to-Entities для добавления новой сущности, но получаю следующую ошибку:

Невозможно вставить явное значение для столбца идентификаторов в таблицу XXX, если для IDENTITY_INSERT установлено значение OFF.

Я сгенерировал таблицы автоматически, поэтому тип столбца ID - int и по умолчанию установлен на 0. Я не могу установить его в NULL, потому что он не допускает NULL.

Я не хочу явно устанавливать значение, я просто хочу, чтобы оно автоматически увеличивалось, как должно.

Вот мой код:

Person person =new Person()
{
     FirstName="Dan",
     Age=22
};
db.Persons.Add(person);
db.SaveChanges();

Класс Person (сгенерированный из db):

public partial class Person
{
  public int ID { get; set; }
  public string FirstName { get; set; }
  public int Age { get; set; }
}

Заранее благодарим за любую помощь


person chana    schedule 20.01.2020    source источник
comment
I generated the tables automatically что это значит? Вы не разместили код, который превращает ID в IDENTITY, так как же он стал таковым?   -  person Panagiotis Kanavos    schedule 20.01.2020
comment
Я сгенерировал их, запустив Scaffold-DbContext ... и установил идентификатор в моей базе данных.   -  person chana    schedule 20.01.2020
comment
если столбец уже имел атрибут IDENTITY, Scaffold должен был передать код FluentAPI как минимум. Если вы использовали параметр -DataAnnotations, он также должен был выдать атрибуты. Как выглядит ваш код конфигурации DbContext?   -  person Panagiotis Kanavos    schedule 20.01.2020
comment
Однако, если вы установите IDENTITY после scaffolding, вам необходимо регенерировать классы.   -  person Panagiotis Kanavos    schedule 20.01.2020


Ответы (2)


Вы должны сообщить EF Core, что ID является генерируется базой данных. Один из способов сделать это - использовать DatabaseGenerated, например:

public partial class Person
{
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  public int ID { get; set; }
  public string FirstName { get; set; }
  public int Age { get; set; }
}

Параметр DatabaseGeneratedOption.Identity сообщает EF Core, что база данных создает новые значения при вставке записи. Без этого EF Core включил бы значение свойства ID в команду INSERT.

person Panagiotis Kanavos    schedule 20.01.2020
comment
Разве это не означает, что каждый раз, когда я обновляю схему таблиц из базы данных, мне придется это делать снова? - person chana; 20.01.2020
comment
@chana на этапе генерации кода этот атрибут должен был быть добавлен в первую очередь. Либо так, либо добавьте вызов ValueGeneratedOnAdd(); в конфигурацию DbContext. Как вы создавали эти классы? Как выглядит код DbContext? - person Panagiotis Kanavos; 20.01.2020
comment
Я создал эти классы, запустив Scaffold-DbContext Server = xxxx; Database = xxx; User Id = xxx; Пароль = xxx Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models 'в моей консоли pm - person chana; 20.01.2020

Вы должны добавить следующие атрибуты в определение вашего класса:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
....
public partial class Person
{
  [Key]
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  public int ID { get; set; }

  public string FirstName { get; set; }
  public int Age { get; set; }
}

Ключ атрибут означает, что поле должно быть первичным ключом, а DatabaseGenerated сообщает о способе генерации ключа.

person Miamy    schedule 20.01.2020
comment
@ Miamy - разве это не значит, что каждый раз, когда я обновляю схему таблиц из базы данных, мне придется это делать снова? - person chana; 20.01.2020
comment
По крайней мере, вы должны проверить, присутствуют ли эти строки в сгенерированном файле. Я думаю, теоретически ядро ​​EF может добавлять их автоматически на основе метаданных db, но на данный момент оно этого не делает (насколько я знаю). - person Miamy; 20.01.2020