自数据库创建以来,支持<Database>上下文的模型已更改

Ash*_*pta 245 .net code-first entity-framework-4

错误消息:

"自创建数据库以来,支持'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());
}
Run Code Online (Sandbox Code Playgroud)

上下文类:

public class AddressBook : DbContext
{
    public AddressBook()
    { }
    public AddressBook(DbModel AddressBook)
        : base(AddressBook)
    {

    }
    public DbSet<Contact> contacts { get; set; }
    public DbSet<Address> Addresses { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

和连接字符串:

<?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>
Run Code Online (Sandbox Code Playgroud)

因此,数据库名称为"AddressBook",当我尝试将联系人对象添加到上下文时发生错误.我在这里错过了什么吗?

Mat*_*ear 389

现在是:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    Database.SetInitializer<YourDbContext>(null);
    base.OnModelCreating(modelBuilder);
}
Run Code Online (Sandbox Code Playgroud)

在YourDbContext.cs文件中.

  • 比Global.asax更好的是将它放在DbContext类的构造函数中.这样,它适用于使用上下文的每个站点,而不仅仅是由Global.asax文件控制的一个站点. (48认同)
  • Ps,这是在Global.asax Application_Start()中 (13认同)
  • 可能最好将它放在上下文类的静态构造函数中,因此它只被调用一次 - 如本例中的视频:http://msdn.microsoft.com/en-us/data/jj572367 (7认同)
  • 它应该放在受保护的覆盖空内OnModelCreating(DbModelBuilder modelBuilder){Database.SetInitializer <YourDbContext>(null); base.OnModelCreating(模型构建器); } (3认同)

Ran*_*ndy 133

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

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

"自创建数据库以来,支持'Production'上下文的模型已经改变.手动删除/更新数据库,或者Database.SetInitializer使用IDatabaseInitializer实例调用."

以下是该怎么做以及如何处理它:

首次创建模型时,我们运行DatabaseInitializer来执行创建数据库(如果不存在)或添加种子数据等操作.默认的DatabaseInitializer尝试将使用模型所需的数据库模式与存储在使用数据库创建的EdmMetadata表中的模式的哈希进行比较(当Code First是创建数据库的模式时).现有数据库将没有EdmMetadata表,因此不会有哈希...如果缺少该表,今天的实现将抛出.我们将在发送fial版本之前更改此行为,因为它是默认版本.在此之前,现有数据库通常不需要任何数据库初始化程序,因此可以通过调用以下内容类型来关闭它:

Database.SetInitializer<YourDbContext>(null);
Run Code Online (Sandbox Code Playgroud)

杰夫

  • 我今天尝试了这个,我不再得到"模型已经改变",而是我得到"无效的对象名称'dbo.Table'" (9认同)
  • 杰夫希望这是一个解决方法,但它已经两年多了,并且仍然需要将SetInitializer设置为null.对?那么有人可以解释这是如何适应迁移工作流程的. (3认同)
  • @jakejgordon:我也使用EF6但是如果它在Global.asax中,它只能解决运行网站时的问题.如果您有单元测试,那么您就是OOL.最好把它放在YourDbContext的构造函数中.这为每个项目修复了它,包括网站和测试项目. (2认同)

Tom*_*kel 39

对于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);
Run Code Online (Sandbox Code Playgroud)

是的,Matt Frear是对的.UPDATE -EDIT: 警告是我同意其他人的意见,而不是将此代码添加到添加到DbContext类的global.asax中

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

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

目前我正在使用Entity Framework 6.1.3 /.net 4.6.1


chr*_*man 31

此修复程序在CTP5之后不再有效.

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


Sha*_*Ali 27

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

delete FROM [dbo].[__MigrationHistory]
Run Code Online (Sandbox Code Playgroud)

  • 你救了我的命!谢谢你。 (2认同)
  • 不要删除 __MigrationsHistory 表,除非您完全理解 __MigrationsHistory 的用途,并且愿意手动协调代码和数据库之间的差异,并在生产中进行相同的更改。 (2认同)

Ash*_*pta 19

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

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

  • 对于更高版本的EF,这也不再可能了,也就是``modelBuilder.Conventions.Remove <IncludeMetadataConvention>();``对情况没有帮助.DbDatabase.SetInitialzer(NULL); 确实有效. (12认同)

goo*_*all 16

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

System.Data.Entity.Database.SetInitializer(new System.Data.Entity.DropCreateDatabaseIfModelChanges<ProjectName.Path.Context>());
Run Code Online (Sandbox Code Playgroud)

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


Ser*_*gan 8

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

  • 控制台应用程序"DataModel"主要使用as作为程序集,其中包含我的所有代码第一个实体,DbContext,Mirgations和通用存储库.我已经在此项目中包含了单独的空本地数据库文件(在DataModel/App_Data文件夹中),以便能够从Package Manager控制台生成迁移.
  • WebApi,它引用DataModel项目并使用WebApi/App_Data文件夹中的本地数据库文件,该文件未包含在项目中

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

我的环境:

  • Windows 8.1 x64
  • Visual Studio 2015 Professional,更新1
  • 我的所有项目都针对.NET Framework 4.6.1
  • 来自NuGet的EntityFramework 6.1.3

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

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

    <configuration>
      <connectionStrings>
        <add name="MyConnectionString" connectionString="...">
      </connectionStrings>
    <configuration>
    
    Run Code Online (Sandbox Code Playgroud)

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

     public partial class MyDbContext : DbContext
     {
        public MyDbContext()
           : base("name=MyConnectionString"){}
        ...
    
    Run Code Online (Sandbox Code Playgroud)
  5. 在使用Package Manager控制台之前,请确保使用正确的数据库进行更新或生成迁移,并将所需项目设置为解决方案的启动项目.对于连接到数据库,它将使用该.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>()); 
               ...
    
    Run Code Online (Sandbox Code Playgroud)

    我试过干净并重建解决方案,但它没有帮助,比我从WebApi完全删除bin和obj文件夹,从WebApi/App_Data删除数据库文件,构建,重新启动WebApi,向它发出请求,它创建了正确的数据库 - 延迟初始化(使用上面的行),它对应于最新的迁移和异常并没有出现更多. 所以,这可能会解决您的问题:

    1. 从您的启动项目中删除手动bin,obj文件夹(生成/更新您的数据库)
    2. 构建您的启动项目或更好地清理并重建您的所有解决方案.
    3. 通过启动项目(将执行上面的行)或使用程序包管理器控制台"update-database"命令重新创建数据库.
    4. 手动检查生成的db和__MirgationHistory是否与最新的迁移脚本相对应.


Rob*_*och 5

对我来说,升级到4.3.1,我只是截断EdmMetaData表或者直接删除它.