Подтвердить что ты не робот

Ввод ключей вручную с помощью платформы Entity Framework

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

Я заметил, что EF устанавливал идентификатор для моих таблиц, автоматически увеличиваясь на 1 каждый раз, полностью игнорируя значение, введенное вручную для этого поля. После некоторых поисков я понимаю, что правильный способ отключить это поведение:

modelBuilder.Entity<Event>().Property(e => e.EventID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

Однако теперь я просто получаю эту ошибку, и я понятия не имею, почему:

Необработанное исключение: System.Data.Entity.Infrastructure.DbUpdateException: ошибка при обновлении записей. См. Внутреннее исключение для Детали. ---

System.Data.UpdateException: при обновлении записей произошла ошибка. Подробнее см. Внутреннее исключение. --- >   System.Data.SqlClient.SqlException: не может вставить явное значение для   столбец идентификатора в таблице "События", когда для параметра IDENTITY_INSERT установлено значение "ВЫКЛ".

Если это полезно, вот класс POCO, о котором идет речь:

public class Event
{
    [Key, Required]
    public int EventID { get; set; }

    public string EventType { get; set; } //TODO: Event Type Table later on
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }

    public virtual ICollection<Match> Matches { get; set; }
    public virtual ICollection<EventParticipation> EventParticipation { get; set; }
}

Спасибо заранее.

4b9b3361

Ответ 1

По умолчанию Entity Framework предполагает, что целочисленный первичный ключ является сгенерированной базой данных (эквивалентно добавлению атрибута HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity) или вызову Property(e => e.EventID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); в Fluent API.

Если вы посмотрите на миграцию, которая создает таблицу, вы должны увидеть это:

   CreateTable(
                "dbo.Events",
                c => new
                    {
                        EventID = c.Int(nullable: false, identity: true),
                        //etc
                    })
                .PrimaryKey(t => t.EventID );

Затем вы изменили модель с использованием Fluent API до DatabaseGenerated.None. EF помещает это в миграцию:

AlterColumn("dbo.Events", "EventID", c => c.Int(nullable: false, identity: false))

И созданный sql это:

ALTER TABLE [dbo].[Events] ALTER COLUMN [EventID] [int] NOT NULL

Что на самом деле действительно приседает. Удаление идентификатора из столбца не является тривиальным. Вам нужно отбросить и воссоздать таблицу или создать новый столбец, затем вам нужно скопировать данные и исправить внешние ключи. Поэтому неудивительно, что EF не делает этого для вас.

Вам нужно выяснить, как лучше всего это сделать для себя. Теперь вы можете откатить свои миграции до 0 и повторно заново с нуля, если вы указали DatabaseGeneratedOption.None, или вы можете вручную изменить миграцию, чтобы удалить и воссоздать таблицу.

Или вы можете удалить и восстановить столбец:

DropColumn("Customer", "CustomerId"); 
AddColumn("Customer", "CustomerId", c => c.Long(nullable: false, identity: false));

ИЗМЕНИТЬ Или вы можете Включение и выключение идентификации идентификации с помощью пользовательской миграции

Ответ 2

Поскольку я предпочитаю атрибуты, здесь альтернатива ради полноты:

[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }