.net 自创建数据库以来,支持 <Database> 上下文的模型已更改
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3600175/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
The model backing the <Database> context has changed since the database was created
提问by Ashish Gupta
The error message :
错误信息:
"The model backing the 'AddressBook' context has changed since the database was created. Either manually delete/update the database, or call Database.SetInitializer with an IDatabaseInitializer instance. For example, the RecreateDatabaseIfModelChanges strategy will automatically delete and recreate the database, and optionally seed it with new data."
“自数据库创建以来,支持‘AddressBook’上下文的模型已更改。手动删除/更新数据库,或使用 IDatabaseInitializer 实例调用 Database.SetInitializer。例如,RecreateDatabaseIfModelChanges 策略将自动删除和重新创建数据库,以及可以选择用新数据播种。”
I am trying to use the code-first feature and following is what I wrote:
我正在尝试使用代码优先功能,以下是我写的:
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());
}
The context class:
上下文类:
public class AddressBook : DbContext
{
public AddressBook()
{ }
public AddressBook(DbModel AddressBook)
: base(AddressBook)
{
}
public DbSet<Contact> contacts { get; set; }
public DbSet<Address> Addresses { get; set; }
}
and the connection string:
和连接字符串:
<?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>
So, the database name is "AddressBook" and the error happens when I trying to add the contact object to the context. Am I missing anything here?
因此,数据库名称是“AddressBook”,当我尝试将联系人对象添加到上下文时会发生错误。我在这里错过了什么吗?
回答by Matt Frear
Now it's:
现在是:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<YourDbContext>(null);
base.OnModelCreating(modelBuilder);
}
in your YourDbContext.cs file.
在您的 YourDbContext.cs 文件中。
回答by Randy
Here's some information from Scott Gu's Blogposted by Jeffon what's actually taking place:
以下是Jeff发布的Scott Gu 博客中关于实际发生的事情的一些信息:
For those who are seeing this exception:
"The model backing the 'Production' context has changed since the database was created. Either manually delete/update the database, or call
Database.SetInitializerwith anIDatabaseInitializerinstance."Here is what is going on and what to do about it:
When a model is first created, we run a DatabaseInitializer to do things like create the database if it's not there or add seed data. The default DatabaseInitializer tries to compare the database schema needed to use the model with a hash of the schema stored in an EdmMetadata table that is created with a database (when Code First is the one creating the database). Existing databases won't have the EdmMetadata table and so won't have the hash…and the implementation today will throw if that table is missing. We'll work on changing this behavior before we ship the fial version since it is the default. Until then, existing databases do not generally need any database initializer so it can be turned off for your context type by calling:
Database.SetInitializer<YourDbContext>(null);Jeff
对于那些看到此异常的人:
“自创建数据库以来,支持‘生产’上下文的模型已更改。手动删除/更新数据库,或
Database.SetInitializer使用IDatabaseInitializer实例调用。”这是正在发生的事情以及如何处理它:
首次创建模型时,我们运行 DatabaseInitializer 来执行诸如创建数据库(如果数据库不存在)或添加种子数据之类的操作。默认的 DatabaseInitializer 尝试将使用模型所需的数据库架构与存储在使用数据库创建的 EdmMetadata 表中的架构散列进行比较(当 Code First 是创建数据库的时候)。现有的数据库不会有 EdmMetadata 表,因此不会有哈希......如果该表丢失,今天的实现将抛出。我们将在发布最终版本之前更改此行为,因为它是默认版本。在此之前,现有数据库通常不需要任何数据库初始值设定项,因此可以通过调用为您的上下文类型关闭它:
Database.SetInitializer<YourDbContext>(null);杰夫
回答by Tom Stickel
For Entity Framework 5.0.0.0 - 6.1.3
对于实体框架 5.0.0.0 - 6.1.3
You DOindeed want to do the following:
你不要确实要做到以下几点:
1. using System.Data.Entity; to startup file (console app --> Program.cs / mvc --> global.asax
2. Database.SetInitializer<YourDatabaseContext>(null);
Yes, Matt Frear is correct. UPDATE -EDIT:Caveat is that I agree with others in that instead of adding this code to global.asax added to your DbContext class
是的,马特弗雷尔是正确的。更新 - 编辑:警告是我同意其他人的观点,而不是将此代码添加到 global.asax 添加到您的 DbContext 类
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// other code
Database.SetInitializer<YOURContext>(null);
// more code here.
}
As others mentioned this also is good for handling the unit testing.
正如其他人提到的,这也有利于处理单元测试。
Currently I am using this with Entity Framework 6.1.3 /.net 4.6.1
目前我在 Entity Framework 6.1.3 /.net 4.6.1 中使用它
I will come back to provide a CORE snippet in the near future.
我会在不久的将来回来提供 CORE 片段。
回答by Shafqat Ali
Just run the followng sql command in SQL Server Management Studio:
只需在 SQL Server Management Studio 中运行以下 sql 命令:
delete FROM [dbo].[__MigrationHistory]
回答by chrisortman
This fix no longer works after CTP5.
此修复在 CTP5 之后不再起作用。
You have to do Database.SetInitializer<YourContext>(null);
你必须要做 Database.SetInitializer<YourContext>(null);
回答by Ashish Gupta
Just found out the answer and thought of updating here. Just need to do the following.
刚刚找到答案并想到在这里更新。只需要执行以下操作。
public class AddressBook: DbContext
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.IncludeMetadataInDatabase = false;
}
}
回答by goodies4uall
Or you can put this line in your Global.asax.cs file under Application_Start():
或者您可以将此行放在 Application_Start() 下的 Global.asax.cs 文件中:
System.Data.Entity.Database.SetInitializer(new System.Data.Entity.DropCreateDatabaseIfModelChanges<ProjectName.Path.Context>());
Make sure to change ProjectName.Path.Context to your namespace and context. If using code first this will delete and create a new database whenever any changes are made to the schema.
确保将 ProjectName.Path.Context 更改为您的命名空间和上下文。如果首先使用代码,这将在对架构进行任何更改时删除并创建一个新数据库。
回答by Sergey Kulgan
I spent many days to solve this issue, analyzed many different posts and tried many options and finally fixed.This 2 projects in my solution using EF code first migrations:
我花了很多天来解决这个问题,分析了很多不同的帖子,尝试了很多选择,最后解决了。我的解决方案中的这 2 个项目使用 EF 代码首先迁移:
- Console Application "DataModel" that mainly using as assembly which contains all my code first entities, DbContext, Mirgations and generic repository. I have included to this project separate empty local database file (in DataModel/App_Data folder) to be able generate migrations from Package Manager Console.
- WebApi, which references to DataModel project and uses local database file from WebApi/App_Data folder, that not included in project
- 控制台应用程序“DataModel”主要用作程序集,其中包含我所有的代码优先实体、DbContext、MiRGations 和通用存储库。我已经在这个项目中包含了单独的空本地数据库文件(在 DataModel/App_Data 文件夹中),以便能够从包管理器控制台生成迁移。
- WebApi,它引用 DataModel 项目并使用 WebApi/App_Data 文件夹中的本地数据库文件,该文件未包含在项目中
I got this error when requested WebApi...
请求 WebApi 时出现此错误...
My environment:
我的环境:
- Windows 8.1 x64
- Visual Studio 2015 Professional with Update 1
- all my projects targeted for .NET Framework 4.6.1
- EntityFramework 6.1.3 from NuGet
- 视窗 8.1 x64
- 带有更新 1 的 Visual Studio 2015 Professional
- 我所有针对 .NET Framework 4.6.1 的项目
- 来自 NuGet 的 EntityFramework 6.1.3
Here I collected all the remarks you should pay attention and all conditions/requirements which must be met, to avoid mentioned exception :
在这里,我收集了您应该注意的所有备注以及必须满足的所有条件/要求,以避免提到的例外情况:
- You should use only one version of EntityFramework Nuget package for all projects in your solution.
- Database, created by running sequentially all migration scripts should have the same structure/schema as you target database and correspond to entity model. Following 3 things must exactly correspond/reflect/match each other:
- Your all migration script up to last
- Current code first entity model state (DbContext, entities)
- Target database
- Target database (mdf file) should be updated/correspond up to last migration script. Verify that "__MigrationHistory" table in your target database contains records for all migration scripts that you have, it means that all migration scripts was successfully applied to that database. I recommend you to use Visual Studio for generation correct code first entities and context that corresponds to your database, Project -> Add New Item -> ADO.NET Entity Data Model -> Code First from database:
Of course, as an alternative, if you have no database you can write manually model (code first entities and context) and then generate initial migration and database. Name of connection string e.g. MyConnectionStringin config file of startup project (Web.config/App.config):
<configuration> <connectionStrings> <add name="MyConnectionString" connectionString="..."> </connectionStrings> <configuration>should be equal to parameter passed in constructor of your DbContext:
public partial class MyDbContext : DbContext { public MyDbContext() : base("name=MyConnectionString"){} ...- Before using Package Manager Console, make sure that you are using correct database for update or generate migration and needed project is set as startup project of solution.For connect to database it will use connection string from that .config file, which in project, that is set as startup project.
And the main, which fixed my issue:It is weird, but in my WebApi/bin folder DataModel.exe was old, not refreshed since last build. Since migrations was embedded in my assembly DataModel.exe then my WebApi updated database using old mirgations. I was confused why after updating database in WebApi it not corresponds to latest migration script from DataModel. Following code automatically creates(if not exists) or updates to latest migration local database in my WebApi/App_Data folder.
public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { Database.SetInitializer(new MigrateDatabaseToLatestVersion<ODS_DbContext, Configuration>()); ...I tried clean and rebuild solution but it did not help, than I completely removed bin and obj folders from WebApi, deleted database files from WebApi/App_Data, built, restarted WebApi, made request to it, it created correct database - lazy initialization (using lines above), which corresponds to latest migration and exception didn't appear more. So, this may fix your problem:
- remove manually bin, obj folders from your startup project(which generates/updates your database)
- build your startup project or better clean and rebuild all you solution.
- recreate database by starting project (will execute lines above) or use Package Manager Console "update-database" command.
- manually check whether generated db and __MirgationHistory corresponds to latest migration script.
- 对于解决方案中的所有项目,您应该只使用一个版本的 EntityFramework Nuget 包。
- 通过顺序运行所有迁移脚本创建的数据库应与目标数据库具有相同的结构/模式并对应于实体模型。以下三件事必须完全对应/反映/匹配:
- 您的所有迁移脚本直到最后
- 当前代码第一实体模型状态(DbContext,实体)
- 目标数据库
- 目标数据库(mdf 文件)应更新/对应于上次迁移脚本。验证目标数据库中的“__MigrationHistory”表是否包含您拥有的所有迁移脚本的记录,这意味着所有迁移脚本都已成功应用于该数据库。我建议您使用 Visual Studio 生成与您的数据库对应的正确代码优先实体和上下文,项目 -> 添加新项目 -> ADO.NET 实体数据模型 -> 数据库中的代码优先:
当然,作为替代,如果您没有数据库,您可以手动编写模型(代码优先实体和上下文),然后生成初始迁移和数据库。 连接字符串的名称,例如启动项目配置文件中的MyConnectionString(Web.config/App.config):
<configuration> <connectionStrings> <add name="MyConnectionString" connectionString="..."> </connectionStrings> <configuration>应该等于在你的 DbContext 的构造函数中传递的参数:
public partial class MyDbContext : DbContext { public MyDbContext() : base("name=MyConnectionString"){} ...- 在使用Package Manager Console之前,请确保您使用正确的数据库进行更新或生成迁移,并将所需项目设置为解决方案的启动项目。对于连接到数据库,它将使用该 .config 文件中的连接字符串,该文件在项目中被设置为启动项目。
主要解决了我的问题:这很奇怪,但在我的 WebApi/bin 文件夹中 DataModel.exe 很旧,自上次构建以来没有刷新。由于迁移嵌入在我的程序集 DataModel.exe 中,因此我的 WebApi 使用旧的 mirgations 更新了数据库。我很困惑为什么在 WebApi 中更新数据库后它不对应于来自 DataModel 的最新迁移脚本。以下代码会在我的 WebApi/App_Data 文件夹中自动创建(如果不存在)或更新到最新的迁移本地数据库。
public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { Database.SetInitializer(new MigrateDatabaseToLatestVersion<ODS_DbContext, Configuration>()); ...我尝试了清理和重建解决方案,但没有帮助,我从 WebApi 中完全删除了 bin 和 obj 文件夹,从 WebApi/App_Data 中删除了数据库文件,构建、重新启动了 WebApi,向它发出了请求,它创建了正确的数据库 - 延迟初始化(使用行),这对应于最新的迁移和异常没有出现更多。 因此,这可能会解决您的问题:
- 从您的启动项目中手动删除 bin、obj 文件夹(生成/更新您的数据库)
- 构建您的启动项目或更好地清理和重建您的所有解决方案。
- 通过启动项目(将执行上面的行)或使用包管理器控制台“更新数据库”命令重新创建数据库。
- 手动检查生成的 db 和 __MilgationHistory 是否对应于最新的迁移脚本。
回答by Robert Koch
For me, with the upgrade to 4.3.1, I just truncate the EdmMetaData table or just delete it outright.
对我来说,升级到 4.3.1 后,我只是截断了 EdmMetaData 表或直接将其删除。
回答by Eric Schneider
For VB.NET developers:
对于 VB.NET 开发人员:
Add the following line to the Glabal.asax.vb file, at the end of method Application_Start()
将以下行添加到 Glabal.asax.vb 文件,在 Application_Start() 方法的末尾
Database.SetInitializer(Of ApplicationDbContext)(Nothing)
Change ApplicationDbContext to your specific Db context.
将 ApplicationDbContext 更改为您的特定 Db 上下文。

