支持<Database>自数据库创建以来,上下文发生了变化

错误信息:

“自数据库创建以来,支持‘AddressBook’上下文的模型已经发生了变化。手动删除/更新数据库,或者调用database。带有IDatabaseInitializer实例的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”,当我试图将联系人对象添加到上下文时发生错误。我遗漏了什么吗?

259923 次浏览

刚刚找到答案,想在这里更新。只需要做以下事情。

public class AddressBook: DbContext
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.IncludeMetadataInDatabase = false;
}
}

此修复在CTP5之后不再有效。

你必须做Database.SetInitializer<YourContext>(null);

现在是:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<YourDbContext>(null);
base.OnModelCreating(modelBuilder);
}

在你的YourDbContext.cs文件中。

下面是Scott Gu的博客杰夫发布的关于实际发生的事情的一些信息:

对于那些看到这个例外的人:

"支持'Production'上下文的模型自 创建数据库。手动删除/更新数据库,或者 使用IDatabaseInitializer实例调用Database.SetInitializer。" < / p >

以下是正在发生的事情以及如何应对:

当模型第一次创建时,我们运行DatabaseInitializer来做 比如,如果没有数据库,就创建数据库,或者添加种子数据。 默认的DatabaseInitializer尝试比较数据库模式 对象中存储的模式的散列需要使用该模型 与数据库一起创建的EdmMetadata表(当Code First为 创建数据库的那个)。现有数据库将没有 EdmMetadata表等不会有散列和实现 如果那张桌子不见了,今天就扔。我们将努力改变这一点 行为,因为它是默认的。 在此之前,现有的数据库通常不需要任何数据库 初始化式,因此可以通过调用

来为你的上下文类型关闭它
Database.SetInitializer<YourDbContext>(null);

杰夫

对我来说,在升级到4.3.1之后,我只是截断了EdmMetaData表,或者直接删除它。

或者你可以把这一行放在你的Global.asax.cs文件中的Application_Start():

System.Data.Entity.Database.SetInitializer(new System.Data.Entity.DropCreateDatabaseIfModelChanges<ProjectName.Path.Context>());

确保将ProjectName.Path.Context更改为您的名称空间和上下文。如果先使用代码,那么每当对模式进行任何更改时,都会删除并创建一个新数据库。

在对这个主题进行了一些研究之后,我发现如果您之前在本地sql server express上创建了一个db实例,就会发生这个错误。因此,每当你在db上有更新,并试图更新db/在db上运行一些代码,而不运行Update Database命令使用Package Manager Console;首先,您必须手动删除本地SQL express上以前的db。

此外,除非你的配置中有__abc0,否则这个解决方案是有效的。

如果你使用版本控制系统(git,svn等)和其他一些开发人员在生产阶段更新db对象,那么每当你更新代码库并运行应用程序时,这个错误就会出现。

如上所述,在代码基础上有一些解决方案。然而,在某些情况下,这是最实用的方法。

我正在阅读Pro ASP。NET MVC 4的书,也遇到了同样的问题。对我来说,在做了书中“添加模型验证”部分中规定的更改后,我开始遇到这个问题。我解决这个问题的方法是将我的数据库从localdb移动到成熟的SQL Server 2012服务器。(顺便说一句,我知道我很幸运可以切换到成熟版本,所以不要恨我。;-)))一定是与db通信的某些东西导致了这个问题。

对于实体框架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);

是的,马特·弗雷尔是对的。更新编辑:警告是,我同意其他人的观点,而不是将此代码添加到全局。asax添加到你的DbContext类

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// other code
Database.SetInitializer<YOURContext>(null);
// more code here.
}

正如其他人提到的,这也有利于处理单元测试。

目前,我正在使用实体框架6.1.3 /.net 4.6.1

在不久的将来,我将回来提供一个CORE片段。

我有这个问题,原来是一个项目指向SQLExpress,但有问题的是指向LocalDb。(在它们各自的web.config中)。愚蠢的疏忽,但值得注意的是,如果其他人正在排除这个问题。

修改Global.asax.cs,包括Application_Start事件:

Database.SetInitializer<YourDatabaseContext>(
new DropCreateDatabaseIfModelChanges<YourDatabaseContext>());

检查以下步骤

  1. Database.SetInitializer(空);——> Global.asax.cs
< p > 2。

  1. 你的Context类名应该匹配 李查一下< / >

我使用数据库。CompatibleWithModel方法(在EF5中可用)在我使用它之前测试模型和DB是否匹配。我在创建上下文之后调用这个方法…

        // 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


}

此错误可能表明连接字符串有问题,以及连接字符串名称是否与数据库上下文声明匹配。

我有这个错误,因为我错误地命名了本地数据库(愚蠢的错误)和web中的连接字符串的名称。“DefaultConnection”的配置与MyDbContext不匹配。

public MyDbContext(): base("DefaultConnection")
{}




<connectionStrings>
<add name="DefaultConnection" ...
</connectionStrings>

VB。NET开发人员:

在方法Application_Start()的末尾向Glabal.asax.vb文件添加以下行

Database.SetInitializer(Of ApplicationDbContext)(Nothing)

将ApplicationDbContext更改为特定的Db上下文。

尝试使用Database SetInitializer,它属于using System.Data.Entity;

在Global.asax

protected void Application_Start()
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<yourContext>());
}

这将在每次模型更改时创建新的数据库。但是您的数据库将是空的。为了用虚拟数据填充它,你可以使用播种。你可以实现为:

播种::

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

好建议,但是在所有情况下都不准确。我算出一个。 请确保你在Visual Studio中使用PM窗口运行“enable-migrations”,迁移文件夹将被添加到你的项目中

确保添加到文件夹中的两个c#类文件将包含所有模型及其各自的属性。

如果您拥有所有这些,就构建解决方案,并发布部署。

逻辑是不能覆盖现有元数据,因为应用程序没有元数据来替换当前元数据。结果,你会得到这样的错误“支持上下文的模型自数据库创建以来已经改变了”

这意味着在上下文上有一些没有执行的更改。 请先运行Add-Migration来生成我们所做的更改(我们可能没有意识到的更改) 然后执行Update-Database

在这里,我想分享另一种防止上下文改变时模型备份错误的方法:

1)打开DbContext文件

2)使用Microsoft.AspNet.Identity.EntityFramework添加命名空间;

< p > 3) public MyDbContext(): base("name=MyDbContext") { 数据库。SetInitializer(新DropCreateDatabaseAlways ()); } < / p >

我花了很多天来解决这个问题,分析了许多不同的帖子,尝试了许多选项,最终解决了 这2个项目在我的解决方案中使用EF代码第一次迁移:

  • 控制台应用程序“DataModel”,主要用作程序集,其中包含我所有的代码第一个实体,DbContext, Mirgations和通用存储库。我在这个项目中包含了单独的空本地数据库文件(在DataModel/App_Data文件夹中),以便能够从包管理器控制台生成迁移。
  • WebApi引用了DataModel项目,并使用了WebApi/App_Data文件夹中的本地数据库文件,该文件不包含在项目中

当请求WebApi时,我得到了这个错误…

我的环境:

  • Windows 8.1 x64
  • Visual Studio 2015 Professional with Update 1
  • 我所有的项目都针对。net Framework 4.6.1
  • EntityFramework 6.1.3 from NuGet

在这里,我收集了所有你应该注意的事项和所有必须满足的条件/要求,以避免提到的例外:

  1. 对于解决方案中的所有项目,您应该只使用一个版本的EntityFramework Nuget包。
  2. 通过顺序运行所有迁移脚本创建的数据库应该具有与目标数据库相同的结构/模式,并对应于实体模型。以下三点必须完全对应/反映/匹配:

当我们为两个应用程序使用一个数据库时,我遇到了同样的问题。在上下文类型节中设置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

在sql Server Management Studio中执行如下sql命令:

delete FROM [dbo].[__MigrationHistory]

我也遇到了同样的问题——重新添加迁移和更新数据库都不起作用,上面的答案似乎都不正确。然后灵感来了——我正在使用多层(一个网页、一个数据和一个业务)。数据层拥有上下文和所有模型。web层从来没有抛出这个异常——它是业务层(我设置为控制台应用程序进行测试和调试)。原来业务层没有使用正确的连接字符串来获取db并创建上下文。所以我将连接字符串添加到业务层(和数据层)的应用程序配置中,然后它就工作了。把这个放在这里,让其他人可能会遇到同样的问题。

以防有人遇到和我一样的情况。

我有数据库首先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

这些解决方案都不适合我们(除了完全禁用模式检查)。最后,我们在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>

创建自定义上下文初始化项:

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);
}
}
}

注意迁移。Configuration是Package Manager Console中由迁移命令行生成的类。您可能需要将迁移的内部修饰符更改为公共修饰符。配置类。

并从您的OmModelCreating注册它:

public partial class MyDbContext : DbContext
{


protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<MyDbContext>(new MyDbContextInitializer());


//other code for creating model
}
}