错误消息:
“自创建数据库以来,支持'AddressBook'上下文的模型已更改。手动删除/更新数据库,或使用IDatabaseInitializer实例调用Database.SetInitializer。例如,RecreateDatabaseIfModelChanges策略将自动删除并重新创建数据库,并可选择为其添加新数据。“
我正在尝试使用代码优先功能,以下是我写的内容:
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>
因此,数据库名称为“AddressBook”,当我尝试将联系人对象添加到上下文时发生错误。我在这里错过了什么吗?
答案 0 :(得分:377)
现在是:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<YourDbContext>(null);
base.OnModelCreating(modelBuilder);
}
在你的YourDbContext.cs文件中。
答案 1 :(得分:128)
以下是Scott Gu's Blog发布的Jeff有关实际发生情况的一些信息:
对于那些看到此例外的人:
“支持'生产'背景的模型自此以后发生了变化 数据库已创建。手动删除/更新数据库,或 使用
Database.SetInitializer
实例调用IDatabaseInitializer
。“以下是该怎么做以及如何应对:
首次创建模型时,我们运行DatabaseInitializer 比如创建数据库(如果不存在)或添加种子数据。 默认的DatabaseInitializer尝试比较数据库架构 需要使用模型与存储在一个模式的哈希 使用数据库创建的EdmMetadata表(当Code First为时) 创建数据库的那个)。现有数据库不具备 EdmMetadata表等不会有哈希...和实现 如果缺少该表,今天将抛出。我们将努力改变这一点 我们发送fial版本之前的行为,因为它是默认值。 在此之前,现有数据库通常不需要任何数据库 初始化程序,因此可以通过调用:
关闭您的上下文类型Database.SetInitializer<YourDbContext>(null);
杰夫
答案 2 :(得分:37)
Entity Framework 5.0.0.0 - 6.1.3
您 DO 确实想要执行以下操作:
1. using System.Data.Entity; to startup file (console app --> Program.cs / mvc --> global.asax
2. Database.SetInitializer<YourDatabaseContext>(null);
是的,Matt Frear是对的。 UPDATE -EDIT:警告我同意其他人的意见,而不是将此代码添加到添加到DbContext类的global.asax
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// other code
Database.SetInitializer<YOURContext>(null);
// more code
}
正如其他人所说,这也有利于处理单元测试。
目前我正在使用Entity Framework 6.1.3 /.net 4.6.1
答案 3 :(得分:29)
此修复程序在CTP5之后不再有效。
你必须Database.SetInitializer<YourContext>(null);
答案 4 :(得分:23)
只需在SQL Server Management Studio中运行followng sql命令:
delete FROM [dbo].[__MigrationHistory]
答案 5 :(得分:19)
刚刚找到答案并想到在这里更新。只需要做以下几点。
public class AddressBook: DbContext
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.IncludeMetadataInDatabase = false;
}
}
答案 6 :(得分:16)
或者您可以将此行放在Application_Start()下的Global.asax.cs文件中:
System.Data.Entity.Database.SetInitializer(new System.Data.Entity.DropCreateDatabaseIfModelChanges<ProjectName.Path.Context>());
确保将ProjectName.Path.Context更改为您的命名空间和上下文。如果首先使用代码,则只要对架构进行任何更改,就会删除并创建新数据库。
答案 7 :(得分:8)
我花了很多天时间来解决这个问题,分析了很多不同的帖子并尝试了很多选项,并且最终修复了。 这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中更新数据库后,它不符合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,向它发出请求,它创建了正确的数据库 - 延迟初始化(使用上面的行),这对应于最新的迁移和异常没有看起来更多。 因此,这可能会解决您的问题:
答案 8 :(得分:5)
对我来说,升级到4.3.1后,我只是截断了EdmMetaData表,或者直接删除它。
答案 9 :(得分:3)
对于VB.NET开发人员:
将以下行添加到Glabal.asax.vb文件中,方法结束时Application_Start()
Database.SetInitializer(Of ApplicationDbContext)(Nothing)
将ApplicationDbContext更改为您特定的Db上下文。
答案 10 :(得分:2)
我遇到了这个问题,结果发现有一个项目指向SQLExpress,但问题是指向LocalDb。 (在各自的web.config中)。愚蠢的监督,但值得注意,以防其他人正在解决此问题。
答案 11 :(得分:2)
我有同样的问题 - 重新添加迁移和更新数据库没有工作,上面的答案似乎都没有。然后灵感来袭我 - 我使用多层(一个网站,一个数据和一个业务)。数据层具有上下文和所有模型。 Web层从未抛出此异常 - 它是业务层(我将其设置为用于测试和调试的控制台应用程序)。结果是业务层没有使用正确的连接字符串来获取数据库并创建上下文。所以我将连接字符串添加到业务层(和数据层)的app配置中,并且中提琴可以工作。把这个放在可能遇到同样问题的其他人身上。
答案 12 :(得分:1)
我使用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
}
答案 13 :(得分:1)
以防有人和我的情况相同。
我有数据库第一个EF,同时使用asp.net身份
所以我的webconfig中有两个connectionStrings,没有问题。碰巧我创建/运行脚本手动生成asp.net身份表,我不应该这样做。
所以DROP首先手动/从脚本创建所有的asp.net身份表。
DROP TABLE __MigrationHistory
DROP TABLE AspNetRoles
DROP TABLE AspNetUserClaims
DROP TABLE AspNetUserLogins
DROP TABLE AspNetUserRoles
DROP TABLE AspNetUsers
答案 14 :(得分:1)
这些解决方案都不适合我们(除了完全禁用模式检查)。最后,我们在我们的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>
答案 15 :(得分:1)
这意味着上下文中有一些尚未执行的更改。 请先运行Add-Migration以生成我们已完成的更改(我们可能不知道的更改) 然后运行Update-Database
答案 16 :(得分:0)
创建自定义上下文初始化程序:
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类的internal到public修饰符。
并从您的OmModelCreating中注册它:
public partial class MyDbContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<MyDbContext>(new MyDbContextInitializer());
//other code for creating model
}
}
答案 17 :(得分:0)
当我们为两个应用程序使用一个数据库时,我遇到了同样的问题。在上下文类型部分设置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>
答案 18 :(得分:0)
然而,好的建议在所有情况下都是如此准确。我想出了一个。 您需要确保在Visual Studio中使用PM窗口运行“enable-migrations”,并且将迁移文件夹添加到您的项目中。
确保添加到文件夹中的两个c#类文件将包含所有模型及其各自的属性。
如果您拥有构建解决方案的所有内容,并且可以部署发布程序。
逻辑是现有元数据无法覆盖,因为您的应用程序没有元数据来替换当前元数据。因此,您收到此错误“自创建数据库以来,支持上下文的模型已更改”
答案 19 :(得分:0)
这很奇怪,但这里的所有答案对我来说都毫无用处。 对我来说,工作初始化
<强> 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
答案 20 :(得分:0)
尝试使用属于使用System.Data.Entity;
的Database SetInitializer在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);
}
}
答案 21 :(得分:0)
此错误可能表示您的连接字符串存在问题,以及您的连接字符串名称是否与数据库上下文声明匹配。
我遇到了这个错误,因为我错误地命名了本地数据库(愚蠢的错误)以及&#34; DefaultConnection&#34;的web.config中的连接字符串的名称。与MyDbContext不匹配,即
public MyDbContext(): base("DefaultConnection")
{}
<connectionStrings>
<add name="DefaultConnection" ...
</connectionStrings>
答案 22 :(得分:0)
检查以下步骤
2。
答案 23 :(得分:0)
修改Global.asax.cs
,包括Application_Start
事件:
Database.SetInitializer<YourDatabaseContext>(
new DropCreateDatabaseIfModelChanges<YourDatabaseContext>());
答案 24 :(得分:0)
我正在阅读Pro ASP.NET MVC 4书,并遇到了你遇到的同样问题。对我来说,在完成本书“添加模型验证”部分中规定的更改后,我开始遇到问题。我解决问题的方法是将我的数据库从localdb移动到成熟的SQL Server 2012服务器。 (顺便说一句,我知道我很幸运,我可以切换到完整的版本,所以不要讨厌我。;-)))必须有一些与db的通信导致问题。
答案 25 :(得分:0)
经过对该主题的一些研究后,我发现如果您之前在本地sql server express上创建了db实例,则基本上会发生错误。因此,每当您对db进行更新并尝试更新db /在db上运行某些代码而不使用Update Database
运行Package Manager Console
命令时;首先,你必须手动删除我们本地sql express上的前一个数据库。
此外,除非您的配置中有AutomaticMigrationsEnabled = false;
,否则此解决方案仍然有效。
如果您使用版本控制系统(git,svn等)和其他一些开发人员在生产阶段更新数据库对象,那么每当您更新代码库并运行应用程序时,此错误就会增加。
如上所述,在代码库上有一些解决方案。但是,对于某些情况,这是最实用的。
答案 26 :(得分:-1)
在这里,我想分享另一种方法,以防止上下文更改时模型支持的错误:
1)打开您的DbContext文件
2)使用Microsoft.AspNet.Identity.EntityFramework;
添加命名空间3) public MyDbContext():base(“name = MyDbContext”) { Database.SetInitializer(new DropCreateDatabaseAlways()); }