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

Entity Framework Code-First: как вручную обновлять базу данных?

Я создал небольшое демонстрационное приложение WPF, которое использует EF Code-First для сохранения своих данных в SQL CE 4.0 DB. Он отлично работает, если я не удаляю свойство из объекта модели. Например, если я удалю "HosteBy" из этого класса.....

public class Dinner
{
    public int DinnerID { get; set; }
    public string Title { get; set; }   
    public DateTime EventDate { get; set; }
    public string Address { get; set; }
    public string HostedBy { get; set; }

    public virtual ICollection<RSVP> RSVPs { get; set; }
}

... это исключает это исключение:

Модель, поддерживающая контекст NerdDinners, изменилась с момента создания базы данных. Либо вручную удалите/обновите базу данных, либо вызовите Database.SetInitializer с экземпляром IDatabaseInitializer. Например, стратегия DropCreateDatabaseIfModelChanges автоматически удалит и воссоздает базу данных и, возможно, запустит ее новыми данными.

Ошибка сохраняется даже после удаления поля "HosteBy" вручную из базы данных. Что мне здесь не хватает? Нужно ли удалять/усекать db или есть другое решение?

4b9b3361

Ответ 1

В первом сценарии, в котором вы изменили первую модель кода, прежде чем перейти и изменить базу данных вручную, ответ заключается в том, чтобы открыть консоль диспетчера пакетов (Nuget) и ввести:

update-database -verbose

Кроме того, поскольку в этом случае вы удаляете столбец, это будет сообщать о том, что он собирается что-то удалить, и ничего не удалит, если вы явно не укажете, что ОК. Таким образом, вы вводите:

update-database -f -verbose

Теперь это удалит столбец, который у вас был в вашей модели. -verbose говорит, что он показывает SQL-сервер. Если вы боитесь просто позволить ему удалить вещи и, скорее, проверить SQL перед запуском, используйте:

update-database -f - script

Вместо этого выгрузите SQL-выход в script, вы можете просмотреть и запустить вручную самостоятельно.

В случае, когда вы продолжали и удаляли столбец в базе данных вручную, теперь у вас есть более сложный сценарий на ваших руках; таблица EdmMetadata, описанная в другом ответе, содержит хеш всей базы данных, которая теперь не соответствует самой базе данных. Вы можете запустить ручной SQL, чтобы вернуть БД к тому, как ожидается Entity Framework (так, как это было до того, как вы вручную изменили его, что вернет его в соответствие с хэшем), проверив, что у вас было до этого и как выглядит ваш db.

Если это невозможно, вы сейчас находитесь в самой уродливой части Entity Framework Code First. Вам нужно исключить хеш-таблицу и перепроектировать db в файлы кода.

Название хэш-таблицы зависит от версии EF. В старшем EF4, о котором вы спрашивали, он называется EdmMetadata. В новом EF5 он называется __MigrationHistory (в разделе "Системные таблицы" в вашей базе данных, если вы смотрите в SQL Server Management Studio). Вам нужно будет уничтожить его.

Хорошая новость на втором этапе, обратное проектирование db в код, заключается в том, что Microsoft выпустила инструмент для бета-тестирования, который сделает это за вас.

Прохождение обратного проектирования a db и EF Power Tools

Вы можете пропустить многие из первых шагов там, так как они просто настраивают базу данных и добавляют к ней какую-то бессмыслицу, чтобы они могли продемонстрировать, что вам нужно сделать: Reverse Engineer a db.

Update:

Также возможно использовать ручную миграцию для работы над этим сценарием. Сделайте резервную копию db, затем запустите:

add-migration WhateverYouWantToCallThis

В сгенерированных командах С# появятся изменения в db EF Migrations, которые должны быть запущены. Теперь вам нужно поработать с ними, чтобы обойти проблемы с тем, что он пытается сделать (например, попытаться удалить удаленные столбцы) и ввести в действие вещи, которые ему нужно будет продвигать (например, добавить обратно таблицу, которую вы все еще имеете в своей модели, но вы вручную удалили в своем db).

Как только вы добавили это и запустили update-database -f, EF Code First просто согласится с верой в то, что вы обновили базу данных так, как она должна быть, и обновите ее хэш на основе конечного результата. Если вы внесли правильные изменения, вы можете продолжить миграцию как обычно. Если это все еще вызывает ошибки, вы обычно можете скопировать команды миграции вручную и удалить их, Восстановить db из резервной копии, снова добавить ручную миграцию и повторить попытку. В худшем случае вы прибегаете к обратному техническому этапу выше.

Ответ 3

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

Решения:

  • Удаление этого варианта. Для этого требуется удалить IncludeMetadataConvention, как описано здесь.
  • Обновление хэша. Для этого потребуется перестроить алгоритм для вычисления хэшей (например, Red Gate.NET Reflector, JetBrains dotPeek, SharpDevelop ILSpy или Telerik JustDecompile) и вычислять новый хэш из скомпилированной модели (или использовать отражение для считывания внутреннего свойства из DbCompiledModel.ModelHash с уже вычисленный хэш), который вы будете хранить в таблице EdmMetadata.
  • Вручную удалять базу данных и создавать EF новую - вы потеряете все данные
  • Установка инициализатора на DropCreateDatabaseIfModelChanges - он автоматически удалит базу данных и создаст новую, если вы измените модель - вы потеряете все данные

Ответ 4

Ознакомьтесь с разделом этой статьи о первых миграциях кода с существующей базой данных
http://msdn.microsoft.com/en-us/data/dn579398

Иногда ваш проект и ваша база данных могут выйти из строя. Возможно, вам придется повторно синхронизировать свою схему с существующей базой данных.



1) Чтобы создать миграцию, основанную на существующей схеме:
Add-Migration InitialCreate

2) Запустите Update-Database после этого, чтобы добавить запись в таблицу _MigrationsHistory, чтобы указать, что миграция завершена до существующей схемы.

Ответ 5

Три простых вещи, которые нужно запомнить при работе над Code First

  • Enable-Migrations
  • Add-Migration
  • Update-Database

Все самоочевидно.

Вам нужно запустить эти команды в консоли диспетчера пакетов вручную. Я опаздываю, но надеюсь, что это поможет