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

Я построил небольшое демонстрационное приложение WPF, которое сначала использует код EF для сохранения своих данных в 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', изменилась с момента создания базы данных. Либо вручную удалить/обновить базу данных или базу данных.SetInitializer с IDatabaseInitializer экземпляр. Например, стратегия DropCreateDatabaseIfModelChanges автоматически удалит и воссоздаст базу данных, а также при необходимости заполнит ее новыми данными.

ошибка сохраняется даже после удаления поля "HosteBy" вручную из базы данных. Я что-то упускаю? Должен ли я удалить/очистить БД или есть другое решение?

5 ответов


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

update-database -verbose

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

update-database -f -verbose

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

update-database-F-script

это вместо этого сбросит SQL в скрипт, который вы можете просмотреть, и запустить вручную самостоятельно.

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

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

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

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

Walk-through обратн-проектируя db, и электроинструменты EF

вы можете пропустить многие из первых шагов, так как они просто настраивают БД и добавляют к нему какую-то ерунду, чтобы они могли продемонстрировать, что вам нужно сделать: реверсивный инженер БД.

обновление:

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

add-migration WhateverYouWantToCallThis

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

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


посмотри

http://weblogs.asp.net/scottgu/archive/2010/07/16/code-first-development-with-entity-framework-4.aspx

Шаг 5: изменение нашей модели


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

решения:

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

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

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



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

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


три простые вещи, которые вам нужно помнить при работе над кодом сначала

  1. Включить-Миграций
  2. Добавить-Миграция
  3. Обновление-Базы Данных

все понятны.

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