Ответ 1
Теперь это:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<YourDbContext>(null);
base.OnModelCreating(modelBuilder);
}
в файле YourDbContext.cs.
Сообщение об ошибке:
"Модель, поддерживающая контекст" Адресная книга ", изменилась с момента создания базы данных. Либо вручную удалите/обновите базу данных, либо вызовите Database.SetInitializer с экземпляром IDatabaseInitializer. Например, стратегия RecreateDatabaseIfModelChanges автоматически удалит и воссоздает базы данных и, возможно, засеять его новыми данными".
Я пытаюсь использовать функцию code-first, и следующее - это то, что я написал:
var modelBuilder = new ModelBuilder();
var model = modelBuilder.CreateModel();
using (AddressBook context = new AddressBook(model))
{
var contact = new Contact
{
ContactID = 10000,
FirstName = "Brian",
LastName = "Lara",
ModifiedDate = DateTime.Now,
AddDate = DateTime.Now,
Title = "Mr."
};
context.contacts.Add(contact);
int result = context.SaveChanges();
Console.WriteLine("Result :- "+ result.ToString());
}
Класс контекста:
public class AddressBook : DbContext
{
public AddressBook()
{ }
public AddressBook(DbModel AddressBook)
: base(AddressBook)
{
}
public DbSet<Contact> contacts { get; set; }
public DbSet<Address> Addresses { get; set; }
}
и строка подключения:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="AddressBook" providerName="System.Data.SqlClient"
connectionString="Data Source=MyMachine;Initial Catalog=AddressBook;
Integrated Security=True;MultipleActiveResultSets=True;"/>
</connectionStrings>
</configuration>
Итак, имя базы данных - "Адресная книга", и ошибка возникает, когда я пытаюсь добавить контактный объект в контекст. Я что-то пропустил здесь?
Теперь это:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<YourDbContext>(null);
base.OnModelCreating(modelBuilder);
}
в файле YourDbContext.cs.
Вот некоторая информация из Scott Gu Blog, опубликованная Джеффом о том, что на самом деле происходит:
Для тех, кто видит это исключение:
"Модель, поддерживающая контекст" Производство ", изменилась с тех пор, как была создана база данных. Либо вручную удалите/обновите базу данных, либо вызовите
Database.SetInitializer
с экземпляромIDatabaseInitializer
.Вот что происходит и что с этим делать:
Когда модель сначала создается, мы запускаем DatabaseInitializer, чтобы сделать такие вещи, как создание базы данных, если она отсутствует или добавить данные семени. По умолчанию DatabaseInitializer пытается сравнить схему базы данных необходимо использовать модель с хешем схемы, хранящейся в Таблица EdmMetadata, созданная с помощью базы данных (когда Code First тот, который создает базу данных). Существующие базы данных не будут иметь Таблица EdmMetadata и поэтому не имеет хеша... и реализации сегодня будет бросать, если эта таблица отсутствует. Мы будем работать над изменением этого прежде чем мы отправим версию fial, так как она по умолчанию. До тех пор существующие базы данных обычно не нуждаются в какой-либо базе данных инициализатор, поэтому его можно отключить для вашего типа контекста, вызвав:
Database.SetInitializer<YourDbContext>(null);
Джефф
Для Entity Framework 5.0.0.0 - 6.1.3
Вы действительно хотите сделать следующее:
1. using System.Data.Entity; to startup file (console app --> Program.cs / mvc --> global.asax
2. Database.SetInitializer<YourDatabaseContext>(null);
Да, Мэтт Фрир прав. ОБНОВЛЕНИЕ -EDIT: Предостережение заключается в том, что я согласен с другими в том, что вместо добавления этого кода в global.asax, добавляемый в ваш класс DbContext
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// other code
Database.SetInitializer<YOURContext>(null);
// more code here.
}
Как уже упоминалось, это также хорошо для модульного тестирования.
В настоящее время я использую это с Entity Framework 6.1.3/.net 4.6.1
Я вернусь, чтобы предоставить фрагмент кода в ближайшем будущем.
Это исправление больше не работает после CTP5.
Вы должны сделать Database.SetInitializer<YourContext>(null);
Просто запустите команду followng sql в SQL Server Management Studio:
delete FROM [dbo].[__MigrationHistory]
Только что узнал ответ и подумал об обновлении здесь. Просто нужно сделать следующее.
public class AddressBook: DbContext
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.IncludeMetadataInDatabase = false;
}
}
Или вы можете поместить эту строку в свой файл Global.asax.cs в Application_Start():
System.Data.Entity.Database.SetInitializer(new System.Data.Entity.DropCreateDatabaseIfModelChanges<ProjectName.Path.Context>());
Обязательно измените имя ProjectName.Path.Context на свое пространство имен и контекст. Если сначала использовать код, это приведет к удалению и созданию новой базы данных всякий раз, когда будут внесены какие-либо изменения в схему.
Я потратил много дней, чтобы решить эту проблему, проанализировал множество разных сообщений и попробовал множество опций и окончательно зафиксировал . Это 2 проекта в моем решении с использованием первых миграций EF-кода:
Я получил эту ошибку при запросе WebApi...
Моя среда:
Здесь я собрал все замечания, на которые вы должны обратить внимание, и все условия/требования, которые должны быть выполнены, чтобы избежать упомянутого исключения:
Название строки подключения, например. MyConnectionString в файле конфигурации запуска проекта (Web.config/App.config):
<configuration>
<connectionStrings>
<add name="MyConnectionString" connectionString="...">
</connectionStrings>
<configuration>
должен быть равен параметру, переданному в конструкторе вашего DbContext:
public partial class MyDbContext : DbContext
{
public MyDbContext()
: base("name=MyConnectionString"){}
...
И основной вопрос, который исправил мою проблему: Это странно, но в моей папке WebApi/bin DataModel.exe был стар, не обновлялся с момента последней сборки. Так как миграции были встроены в мою сборку DataModel.exe, то моя обновленная база данных WebApi использовала старые зеркала. Я был смущен, почему после обновления базы данных в WebApi он не соответствует последней миграции script из DataModel. Следующий код автоматически создает (если не существует) или обновляет последнюю локальную локальную миграцию в моей папке WebApi/App_Data.
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ODS_DbContext, Configuration>());
...
Я попробовал очистить и перестроить решение, но это не помогло, чем я полностью удалил bin и obj из WebApi, удаленные файлы базы данных из WebApi/App_Data, встроенные, перезапущенные WebApi, сделали запрос к нему, создали корректную базу данных - ленивая инициализация (используя строки выше), что соответствует последней миграции и исключению больше не отображалось, Итак, это может решить вашу проблему:
Для меня с обновлением до 4.3.1 я просто обрезаю таблицу EdmMetaData или просто удаляю ее прямо.
Для разработчиков VB.NET:
Добавьте следующую строку в файл Glabal.asax.vb в конце метода Application_Start()
Database.SetInitializer(Of ApplicationDbContext)(Nothing)
Измените ApplicationDbContext на конкретный контекст Db.
У меня была эта проблема, и оказалось, что один проект указывал на SQLExpress, но тот, у кого проблема, указывал на LocalDb. (в их соответствующем web.config). Глупый надзор, но стоит отметить здесь, в случае, если кто-либо другой устранит эту проблему.
У меня была такая же проблема: повторное добавление миграции и обновление базы данных не работало, и ни один из вышеперечисленных ответов не был прав. Затем меня поразило вдохновение - я использую несколько уровней (одна сеть, одна информация и один бизнес). Уровень данных имеет контекст и все модели. Веб-слой никогда не выбрасывал это исключение - это был бизнес-уровень (который я установил как консольное приложение для тестирования и отладки). Оказывается, бизнес-уровень не использовал правильную строку соединения, чтобы получить db и сделать контекст. Поэтому я добавил строку подключения в конфигурацию приложения бизнес-уровня (и слоя данных) и альта, который он работает. Поместите это здесь для других, которые могут столкнуться с одной и той же проблемой.
Я использую метод Database.CompatibleWithModel(доступный в EF5) для проверки соответствия модели и базы данных, прежде чем использовать ее. Я вызываю этот метод сразу после создания контекста...
// test the context to see if the model is out of sync with the db...
if (!MyContext.Database.CompatibleWithModel(true))
{
// delete the old version of the database...
if (File.Exists(databaseFileName))
File.Delete(databaseFileName);
MyContext.Database.Initialize(true);
// re-populate database
}
Это означает, что в контексте, который не был выполнен, произошли некоторые изменения. Сначала запустите Add-Migration, чтобы сгенерировать сделанные нами изменения (изменения, которые нам неизвестны) А затем запустите Update-Database
На всякий случай у кого-то есть тот же сценарий, что и мой.
У меня есть база данных сначала EF и в то же время с использованием идентификатора asp.net
поэтому у меня есть два connectionStrings в моем webconfig, и с этим нет никаких проблем. Случилось так, что я создал/запустил скрипты для генерации вручную таблиц идентификаторов asp.net, которых я не должен.
поэтому DROP сначала создайте все идентификационные таблицы asp.net, созданные вами вручную/из сценариев.
DROP TABLE __MigrationHistory
DROP TABLE AspNetRoles
DROP TABLE AspNetUserClaims
DROP TABLE AspNetUserLogins
DROP TABLE AspNetUserRoles
DROP TABLE AspNetUsers
Ни одно из этих решений не будет работать для нас (кроме отключения проверки схемы вообще). В итоге у нас был пропущенный матч в нашей версии Newtonsoft.json
Наш AppConfig не получил правильное обновление:
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.0.0.0" newVersion="7.0.0.0" />
</dependentAssembly>
Решение заключалось в том, чтобы исправить версию сборки до той, которую мы фактически развертывали
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly>
После некоторых исследований по этой теме я обнаружил, что ошибка происходит в основном, если у вас есть экземпляр db, созданный ранее на вашем локальном SQL-сервере Express. Поэтому всякий раз, когда вы обновляете db и пытаетесь обновить db/run некоторый код на db без выполнения команды Update Database
, используя Package Manager Console
; Прежде всего, вы должны удалить предыдущий db на нашем локальном SQL-Express вручную.
Кроме того, это решение работает, если у вас нет AutomaticMigrationsEnabled = false;
в вашей конфигурации.
Если вы работаете с системой управления версиями (git, svn и т.д.), а некоторые другие разработчики обновляют объекты db на фазе производства, эта ошибка возрастает всякий раз, когда вы обновляете свою базу кода и запускаете приложение.
Как указано выше, для этого на базе кода есть некоторые решения. Однако это наиболее практичный вариант для некоторых случаев.
Я читаю также книгу Pro ASP.NET MVC 4, и столкнулся с той же проблемой, с которой вы столкнулись. Для меня у меня возникла проблема после внесения изменений, предписанных в разделе "Добавление модели валидации" в книге. Как я решил проблему, переместив мою базу данных с localdb на полномасштабный сервер SQL Server 2012. (Кстати, я знаю, что мне повезло, что я могу перейти на полномасштабную версию, так что не ненавидите меня.;-))) Должно быть что-то с сообщением с db, которое вызывает проблему.
Измените Global.asax.cs
, включая событие Application_Start
, с помощью:
Database.SetInitializer<YourDatabaseContext>(
new DropCreateDatabaseIfModelChanges<YourDatabaseContext>());
Проверьте следующие шаги
2.
Эта ошибка может указывать на проблему с вашей строкой подключения и соответствует ли имя строки подключения описанию контекста базы данных.
У меня была эта ошибка, потому что я неправильно назвал локальную базу (глупая ошибка), а имя строки подключения в файле web.config "DefaultConnection" не соответствует MyDbContext i.e.
public MyDbContext(): base("DefaultConnection")
{}
<connectionStrings>
<add name="DefaultConnection" ...
</connectionStrings>
Попробуйте использовать Database SetInitializer, который принадлежит System.Data.Entity;
В Global.asax
protected void Application_Start()
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<yourContext>());
}
Это создаст новую базу данных каждый раз, когда ваша модель будет изменена. Но ваша база данных будет пустой. Чтобы заполнить ее фиктивными данными, вы можете использовать Seeding. Что вы можете реализовать как:
Посев::
protected void Application_Start()
{
Database.SetInitializer(new AddressBookInitializer());
----rest code---
}
public class AddressBookInitializer : DropCreateDatabaseIfModelChanges<AddressBook>
{
protected override void Seed(AddressBook context)
{
context.yourmodel.Add(
{
});
base.Seed(context);
}
}
Это странно, но все ответы здесь бесполезны для меня. Для меня работал инициализатор
MigrateDatabaseToLatestVersion
Здесь мое решение (я знаю, это может быть намного проще, но как я его использую):
class MyDbMigrateToLatest : MigrateDatabaseToLatestVersion<MyDbContext, Configuration>
{
}
public class MyDbContext: DbContext
{
public MyDbContext() : base("DbName")
{
SetInitializer();
}
public MyDbContext(string connString) : base(connString)
{
SetInitializer();
}
private static void SetInitializer()
{
if (ConfigurationManager.AppSettings["RebuildDatabaseOnStart"] == "true")
Database.SetInitializer(new MyDbInitializerForTesting());
else
Database.SetInitializer(new MyDbMigrateToLatest());
}
}
public sealed class Configuration : DbMigrationsConfiguration<MyDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(MyDbContext context)
{
// Whatever
}
}
MyDbInitializerForTesting просто наследует от DropCreateDatabaseAlways, поэтому в каком-то конкретном случае (тестирование) вся база данных перестраивается. В противном случае он перенесен в последнюю версию.
Мой источник: https://msdn.microsoft.com/en-us/data/jj591621.aspx#specific
Хорошее предложение, однако, настолько точно во всех случаях. Я все понял. Пожалуйста, убедитесь, что вы запускаете "enable-migrations" с использованием окон PM в Visual Studio, а папка миграции будет добавлена в ваш проект.
Убедитесь, что два файла класса С#, добавленные в папку, будут содержать все ваши модели и их соответствующие свойства.
Если у вас есть все, что построит решение, и publis для развертывания.
Логика заключается в том, что существующие метаданные не могут быть перезаписаны, потому что ваше приложение не имеет метаданных для замены текущего. В результате вы получаете эту ошибку "Модель, поддерживающая контекст, изменилась с момента создания базы данных"
У меня была та же проблема, когда мы использовали одну базу данных для двух приложений. Установка disableDatabaseInitialization="true"
в разделе типа контекста работает для меня.
<entityFramework>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
<contexts>
<context type="PreferencesContext, Preferences" disableDatabaseInitialization="true">
<databaseInitializer type="System.Data.Entity.MigrateDatabaseToLatestVersion`2[[PreferencesContext, Preferences], [Migrations.Configuration, Preferences]], EntityFramework" />
</context>
</contexts>
Подробнее https://msdn.microsoft.com/en-us/data/jj556606.aspx
Создать собственный инициализатор контекста:
public class MyDbContextInitializer : MigrateDatabaseToLatestVersion<MyDbContext, Migrations.Configuration>
{
public override void InitializeDatabase(MyDbContext context)
{
bool exists = context.Database.Exists();
base.InitializeDatabase(context);
if (!exists)
{
MyDbSeed.Seed(context);
}
}
}
Обратите внимание, что Migrations.Configuration - это класс, генерируемый командной строкой миграции в консоли диспетчера пакетов. Вам может потребоваться изменить внутренний на публичный модификатор класса Migrations.Configuration.
И зарегистрируйте его в своем OmModelCreating:
public partial class MyDbContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<MyDbContext>(new MyDbContextInitializer());
//other code for creating model
}
}
Здесь я хочу поделиться другим методом, который предотвращает ошибку поддержки модели при изменении контекста:
1) Откройте файл DbContext
2) Добавьте пространство имен, используя Microsoft.AspNet.Identity.EntityFramework;
3) public MyDbContext(): base ( "name = MyDbContext" ) { Database.SetInitializer(новый DropCreateDatabaseAlways()); }