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

Entity Framework Code First Migrations: значение первичного ключа

У меня есть таблица, в которой хранятся некоторые дополнительные данные для некоторых строк таблицы, например:

public class QuoteExtra
{
    [Key]
    public int QuoteId { get; set; }
    // More fields here
}

Я хотел бы иметь возможность добавлять строки в эту таблицу, где я явно устанавливаю PK.

Если я просто оставлю его, как указано выше, установка значения и отправка строки приводит к тому, что значение будет отброшено и заменено автоматически генерируемым значением из базы данных (а столбец определяется как столбец "Идентификатор" в фактической схеме).

Это кажется правильным решением:

public class QuoteExtra
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int QuoteId { get; set; }
    // More fields here
}

Однако это вместо меня вызывает исключение:

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

Итак, как мне написать свой класс, чтобы я мог установить значение Первичного ключа в EF?

Edit:

Я попытался добавить следующую миграцию на основе кода, чтобы установить IDENTITY_INSERT в ON:

public override void Up()
{
    Sql("SET IDENTITY_INSERT QuoteExtra ON");
}

Я запустил его и снова попытался, но получил то же исключение, что и выше. Какая странная база данных отражает этот параметр, а работа с SQL против него напрямую позволяет мне вставлять произвольные значения для первичного ключа, поэтому казалось бы, что Entity Framework сама применяет это правило и не обращает внимания на то, что IDENTITY_INSERT не находится в факт отключен. Нужно ли устанавливать его где-нибудь в самом EF?

Изменить 2:

Я неправильно понял IDENTITY_INSERT; Я предположил, что он однажды установил его для этой таблицы на неопределенный срок. Фактически, он живет до тех пор, пока "Сессия", что означает, что, например, установка в Migration означает, что она живет... до тех пор, пока эта миграция работает, и не имеет отношения к будущим соединениям, таким как мой позже .Add() с EF, что объясняет, почему я до сих пор получил это исключение - БД действительно является источником исключения, а не EF. Поскольку IDENTITY_INSERT ограничен не более чем одной таблицей за сеанс, это довольно неэффективный способ сделать это - не создание столбца Identity PK в первую очередь похоже на лучший маршрут.

4b9b3361

Ответ 1

Это правильный способ создания ПК без использования автоопределения Identity:

public class QuoteExtra
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int QuoteId { get; set; }
    // More fields here
}

Однако, если вы добавите DatabaseGenerated (DatabaseGeneratedOption.None)] после того, как EF Migrations уже создал таблицу, она спокойно ничего не делает для таблицы. Если это ваш сценарий, вам нужно добавить ручную миграцию, чтобы удалить таблицу:

add-migration RecreateQuoteExtra

И в процессе миграции:

public override void Up()
{
    DropTable("QuoteExtra");
}

EF Автоматические миграции затем автоматически воссоздают таблицу без ограничения Identity, которая затем позволит вам установить значение PK в любое время без необходимости запуска каких-либо специальных команд, таких как IDENTITY_INSERT ON.

Похоже, что в EF7 ( "Движение данных" ) это менее разрушительный способ, или вы можете написать много ручного sql самостоятельно в процессе миграции, чтобы создавать временные таблицы и перемещать данные, если вы хотите избежать потеря существующих данных в таблице.

EDIT: в зависимости от вашего сценария EF Migrations не может воссоздать таблицу - если класс уже существует и уже добавлен в ваш DbContext, он просто опустит его и оставьте на нем, то есть ваша миграция вручную должна не только упасть, но и также создайте таблицу. Не так уж много, поскольку код EF Migrations, созданный для вас из add-migration, создаст эти инструкции для вас, но для проверки проблем потребуется немного больше кода.

Ответ 2

Это правильное решение, но только для новой таблицы. Если вы измените параметр сгенерированной базы данных для существующей таблицы, миграции EF не смогут выполнить это изменение, а столбец QuoteId по-прежнему помечен как Identity в базе данных.

Ответ 3

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

Чтобы исправить это, вам нужно удалить свойство identity: true при первом (!) создании столбца (например, Initial-Migration).

Может быть, это поможет кому-то..