261

错误信息:

“支持 '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”,当我尝试将联系人对象添加到上下文时会发生错误。我在这里错过了什么吗?

4

27 回答 27

414

现在是:

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

在 YourDbContext.cs 文件中。

于 2011-05-26T18:08:09.190 回答
138

以下是Jeff发布的Scott Gu 博客中关于实际情况的一些信息:

对于那些看到此异常的人:

“自从创建数据库以来,支持‘生产’上下文的模型已经改变。手动删除/更新数据库,或者Database.SetInitializer使用IDatabaseInitializer实例调用。”

这是正在发生的事情以及如何处理它:

首次创建模型时,我们运行 DatabaseInitializer 来执行诸如创建数据库(如果数据库不存在)或添加种子数据之类的操作。默认的 DatabaseInitializer 尝试将使用模型所需的数据库架构与存储在使用数据库创建的 EdmMetadata 表中的架构哈希进行比较(当 Code First 是创建数据库的人时)。现有的数据库将没有 EdmMetadata 表,因此不会有哈希……如果该表丢失,今天的实现将抛出。在我们发布最终版本之前,我们将努力改变这种行为,因为它是默认的。在此之前,现有数据库通常不需要任何数据库初始化程序,因此可以通过调用以下方法为您的上下文类型关闭它:

Database.SetInitializer<YourDbContext>(null);

杰夫

于 2011-06-02T11:40:18.320 回答
41

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

是的,马特弗雷尔是正确的。更新 - 编辑: 警告是我同意其他人的观点,而不是将此代码添加到 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 一起使用

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

于 2013-02-21T02:25:19.753 回答
35

只需在 SQL Server Management Studio 中运行以下 sql 命令:

delete FROM [dbo].[__MigrationHistory]
于 2016-06-21T17:28:48.130 回答
31

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

你所要做的Database.SetInitializer<YourContext>(null);

于 2011-02-28T15:51:23.587 回答
18

刚刚找到答案并想到在这里更新。只需执行以下操作。

public class AddressBook: DbContext
{
   protected override void OnModelCreating(ModelBuilder modelBuilder)
   {
    modelBuilder.IncludeMetadataInDatabase = false;
   }
}
于 2010-08-30T12:47:13.857 回答
16

或者您可以将此行放在 Application_Start() 下的 Global.asax.cs 文件中:

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

确保将 ProjectName.Path.Context 更改为您的命名空间和上下文。如果首先使用代码,这将在对架构进行任何更改时删除并创建一个新数据库。

于 2012-12-01T01:43:02.007 回答
8

我花了很多天来解决这个问题,分析了很多不同的帖子,尝试了很多选项,最后修复了。 我的解决方案中的这 2 个项目使用 EF 代码优先迁移:

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

请求 WebApi 时出现此错误...

我的环境:

  • 视窗 8.1 x64
  • 带有更新 1 的 Visual Studio 2015 专业版
  • 我所有针对 .NET Framework 4.6.1 的项目
  • 来自 NuGet 的 EntityFramework 6.1.3

在这里,我收集了您应该注意的所有备注以及必须满足的所有条件/要求,以避免提到的异常:

  1. 对于解决方案中的所有项目,您应该只使用一个版本的 EntityFramework Nuget 包。
  2. 通过顺序运行所有迁移脚本创建的数据库应具有与您的目标数据库相同的结构/架构并对应于实体模型。以下三件事必须完全对应/反映/匹配:
    • 您的所有迁移脚本直到最后
    • 当前代码优先实体模型状态(DbContext,实体)
    • 目标数据库
  3. 目标数据库(mdf 文件)应更新/对应于上次迁移脚本。验证目标数据库中的“__MigrationHistory”表是否包含您拥有的所有迁移脚本的记录,这意味着所有迁移脚本都已成功应用于该数据库。我建议您使用 Visual Studio 生成与您的数据库相对应的正确代码优先实体和上下文,项目 -> 添加新项目 -> ADO.NET 实体数据模型 -> 数据库中的代码优先: 当然,作为替代方案,如果您没有数据库,您可以手动编写模型(代码优先实体和上下文),然后生成初始迁移和数据库。
  4. 连接字符串的名称,例如启动项目配置文件中的MyConnectionString (Web.config/App.config):

    <configuration>
      <connectionStrings>
        <add name="MyConnectionString" connectionString="...">
      </connectionStrings>
    <configuration>
    

    应该等于在 DbContext 的构造函数中传递的参数:

     public partial class MyDbContext : DbContext
     {
        public MyDbContext()
           : base("name=MyConnectionString"){}
        ...
    
  5. 在使用Package Manager Console之前,请确保您使用正确的数据库进行更新或生成迁移,并将所需项目设置为解决方案的启动项目。对于连接到数据库,它将使用该 .config 文件中的连接字符串,该文件在项目中设置为启动项目。
  6. 而主要的,它解决了我的问题:这很奇怪,但在我的 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,向它发出请求,它创建了正确的数据库 - 延迟初始化(使用上面的行),这对应于最新的迁移和异常没有出现更多。 因此,这可能会解决您的问题:

    1. 从您的启动项目中手动删除 bin、obj 文件夹(生成/更新您的数据库)
    2. 构建您的启动项目或更好地清理和重建您的所有解决方案。
    3. 通过启动项目(将执行上面的行)或使用包管理器控制台“update-database”命令重新创建数据库。
    4. 手动检查生成的 db 和 __MigationHistory 是否对应最新的迁移脚本。
于 2016-01-14T20:50:46.533 回答
5

对我来说,升级到 4.3.1 后,我只是截断了 EdmMetaData 表或直接将其删除。

于 2012-05-04T12:57:53.420 回答
3

对于 VB.NET 开发人员:

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

Database.SetInitializer(Of ApplicationDbContext)(Nothing)

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

于 2014-09-20T19:15:00.650 回答
2

我遇到了这个问题,结果发现一个项目指向 SQLExpress,但有问题的项目指向 LocalDb。(在他们各自的 web.config 中)。愚蠢的疏忽,但值得注意的是,以防其他人解决此问题。

于 2014-01-02T00:18:50.857 回答
2

这意味着上下文中有一些尚未执行的更改。请先运行 Add-Migration 以生成我们所做的更改(我们可能不知道的更改)然后运行 ​​Update-Database

于 2015-08-22T08:07:48.433 回答
2

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

于 2016-09-30T19:02:15.373 回答
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

        }
于 2014-08-13T09:33:41.093 回答
1

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

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

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


<connectionStrings>
    <add name="DefaultConnection" ...
  </connectionStrings>
于 2014-08-31T20:16:47.207 回答
1

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

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

如果您拥有构建解决方案的所有内容,并发布了部署。

逻辑是现有的元数据不能被覆盖,因为您的应用程序没有元数据来替换当前的。结果,您收到此错误“支持上下文的模型自创建数据库以来已更改”

于 2015-08-04T11:22:46.857 回答
1

以防万一有人和我有同样的情况。

我有数据库第一个 EF,同时使用 asp.net 身份

所以我的webconfig中有两个connectionStrings,这没有问题。碰巧我创建/运行脚本来手动生成我不应该的 asp.net 身份表。

所以首先删除您手动/从脚本创建的所有 asp.net 身份表。

DROP TABLE __MigrationHistory
DROP TABLE AspNetRoles
DROP TABLE AspNetUserClaims
DROP TABLE AspNetUserLogins
DROP TABLE AspNetUserRoles
DROP TABLE AspNetUsers
于 2017-04-15T16:46:32.597 回答
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>
于 2017-07-09T22:52:26.037 回答
0

经过对该主题的一些研究,我发现如果您之前在本地 sql server express 上创建了一个 db 实例,则基本上会发生该错误。因此,每当您对 db 进行更新并尝试更新 db/在 db 上运行一些代码而不使用运行Update Database命令时Package Manager Console;首先,您必须手动删除我们本地 sql express 上以前的数据库。

此外,除非您AutomaticMigrationsEnabled = false;的配置中有此解决方案。

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

如上所述,在代码库上有一些解决方案。但是,对于某些情况,这是最实用的。

于 2012-12-19T14:45:01.823 回答
0

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

于 2013-01-24T20:08:57.063 回答
0

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

Database.SetInitializer<YourDatabaseContext>(
 new DropCreateDatabaseIfModelChanges<YourDatabaseContext>());
于 2014-01-30T17:10:09.007 回答
0

检查以下步骤

  1. Database.SetInitializer(null); --> 在 Global.asax.cs 中

2.

  1. 您的 Context 类名称应与检查它匹配
于 2014-02-03T11:10:58.647 回答
0

尝试使用属于 using 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);
    }

}
于 2014-09-28T15:53:45.310 回答
0

这很奇怪,但这里的所有答案对我来说都没用。对我来说工作的初始化程序

将数据库迁移到最新版本

这是我的解决方案(我知道,它可以更简单,但这就是我使用它的方式):

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

于 2015-06-15T07:03:06.243 回答
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>

查看更多详细信息https://msdn.microsoft.com/en-us/data/jj556606.aspx

于 2016-04-14T21:24:00.280 回答
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 是由 Package Manager Console 中的迁移命令行生成的类。您可能需要将 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
    }
}
于 2018-07-23T12:38:50.550 回答
-3

在这里,我想分享另一种在上下文更改时防止模型支持错误的方法是:

1) 打开你的 DbContext 文件

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

3) public MyDbContext() : base("name=MyDbContext") { Database.SetInitializer(new DropCreateDatabaseAlways()); }

于 2015-09-29T07:19:33.890 回答