代码之家  ›  专栏  ›  技术社区  ›  Ashish Gupta Shiva

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

  •  235
  • Ashish Gupta Shiva  · 技术社区  · 14 年前

    错误消息:

    “自从创建数据库以来,支持“AddressBook”上下文的模型已更改。手动删除/更新数据库,或调用数据库.SetInitializer使用IDatabaseInitializer实例。例如,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”,当我试图将contact对象添加到上下文时会发生错误。我漏了什么吗?

    27 回复  |  直到 8 年前
        1
  •  404
  •   Youngjae    8 年前

    现在是:

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

        2
  •  137
  •   Randy Abel    11 年前

    Scott Gu's Blog 过帐人 Jeff 关于实际发生的事情:

    “支持‘生产’环境的模式自改革以来已经发生了变化 呼叫 Database.SetInitializer 带着一个 IDatabaseInitializer 实例。”

    当第一次创建模型时,我们运行一个DatabaseInitializer 如创建数据库(如果不存在)或添加种子数据。 默认数据库初始值设定项尝试比较数据库架构 需要将模型与存储在 EdmMetadata表,该表是使用数据库创建的(当第一次使用代码时) EdmMetadata表等不会有哈希表和实现 如果那张桌子不见了,今天就扔了。我们会努力改变的 在此之前,现有数据库通常不需要任何数据库 初始值设定项,以便可以通过调用:

    Database.SetInitializer<YourDbContext>(null);
    

        3
  •  40
  •   Tom Stickel    5 年前

    为了 实体框架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.
    }
    

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

    我将在不久的将来回来提供一个核心片段。

        4
  •  33
  •   Shafqat    8 年前

    delete FROM [dbo].[__MigrationHistory]
    
        5
  •  31
  •   Meenal    8 年前

    此修复程序在CTP5之后不再工作。

    Database.SetInitializer<YourContext>(null);

        6
  •  19
  •   Ashish Gupta Shiva    14 年前

    刚找到答案,想在这里更新一下。只需要做以下几点。

    public class AddressBook: DbContext
    {
       protected override void OnModelCreating(ModelBuilder modelBuilder)
       {
        modelBuilder.IncludeMetadataInDatabase = false;
       }
    }
    
        7
  •  16
  •   dwp4ge    12 年前

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

    一定要换衣服项目名称.Path.Context到您的命名空间和上下文。如果先使用代码,则每当对模式进行任何更改时,都将删除并创建一个新数据库。

        8
  •  8
  •   Sergey Kulgan    9 年前

    我花了很多天来解决这个问题,分析了许多不同的帖子,尝试了许多选择和方法 终于修好了。

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

    我的环境:

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

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

    1. 通过顺序运行所有迁移脚本创建的数据库应具有与目标数据库相同的结构/模式,并对应于实体模型。以下三件事必须完全对应/反映/匹配:
      • 当前代码优先实体模型状态(DbContext,entities)
    2. 目标数据库(mdf文件)应该更新/对应到上一个迁移脚本。验证目标数据库中的“\uu MigrationHistory”表是否包含所有迁移脚本的记录,这意味着所有迁移脚本都已成功应用于该数据库。我建议您使用Visual Studio生成与数据库、项目相对应的正确的代码优先实体和上下文->添加新项->ADO.NET实体数据模型->首先从数据库编码:
    3. 我的连接字符串

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

       public partial class MyDbContext : DbContext
       {
          public MyDbContext()
             : base("name=MyConnectionString"){}
          ...
      
    4. 包管理器控制台 ,确保使用正确的数据库进行更新或生成迁移,并且所需的项目设置为 解决方案启动项目。
    5. 主要解决了我的问题: 这很奇怪,但是在我的WebApi/bin文件夹中数据模型.exe已旧,自上次生成后未刷新。因为迁移已嵌入到我的程序集中数据模型.exe然后我的WebApi使用旧的mirgations更新了数据库。我很困惑,为什么在WebApi中更新数据库后,它和DataModel中最新的迁移脚本不一致。下面的代码自动创建(如果不存在)或更新到mywebapi/App\ Data文件夹中的最新迁移本地数据库。

         public class WebApiApplication : System.Web.HttpApplication
         {
             protected void Application_Start()
             {
                 Database.SetInitializer(new MigrateDatabaseToLatestVersion<ODS_DbContext, Configuration>()); 
                 ...
      

      我尝试了清洁和重建解决方案,但没有帮助,比我完全删除 从WebApi中删除bin和obj文件夹,从WebApi/App\u数据中删除数据库文件,构建,重新启动WebApi,向其发出请求,它创建了正确的数据库-延迟初始化(使用上面的行),它对应于最新的迁移,异常不再出现。 因此,这可能会解决您的问题:

      1. 从启动项目中手动删除bin、obj文件夹 (生成/更新数据库)
      2. 通过启动项目(将执行上面的行)或使用包管理器控制台“更新数据库”命令重新创建数据库。
      3. 手动检查生成的db和MirgationHistory是否与最新的迁移脚本相对应。
        9
  •  5
  •   Rob Koch    12 年前

    对我来说,升级到4.3.1后,我只需截断EdmMetaData表或直接删除它。

        10
  •  3
  •   Eric Schneider    10 年前

    Database.SetInitializer(Of ApplicationDbContext)(Nothing)
    

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

        11
  •  2
  •   stuartdotnet    11 年前

    我遇到了这个问题,结果发现有一个项目指向SQLExpress,但有问题的项目指向LocalDb。(以各自的方式)web.config文件). 愚蠢的疏忽,但值得注意的是在这里的情况下,其他人正在解决这个问题。

        12
  •  2
  •   Kerisnarendra    9 年前

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

        13
  •  2
  •   Richard Barker    8 年前

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

        14
  •  1
  •   flobadob    10 年前

    我使用数据库.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
    
            }
    
        15
  •  1
  •   DanAbdn    10 年前

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

    public MyDbContext(): base("DefaultConnection")
    {}
    
    
    <connectionStrings>
        <add name="DefaultConnection" ...
      </connectionStrings>
    
        16
  •  1
  •   Kay Ken    9 年前

    请确保在visualstudio中使用pmwindows运行“启用迁移”,迁移文件夹将添加到项目中。

    如果你已经构建了所有的解决方案,并发布了用于部署的publis。

        17
  •  1
  •   Francis Saul    7 年前

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

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

    所以先放下所有的东西asp.net由您手动/从脚本创建的标识表。

    DROP TABLE __MigrationHistory
    DROP TABLE AspNetRoles
    DROP TABLE AspNetUserClaims
    DROP TABLE AspNetUserLogins
    DROP TABLE AspNetUserRoles
    DROP TABLE AspNetUsers
    
        18
  •  1
  •   AcidPAT    7 年前

    <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>
    
        19
  •  0
  •   Mahmut C    12 年前

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

    此外,除非您 AutomaticMigrationsEnabled = false;

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

        20
  •  0
  •   J3Speaks    12 年前

        21
  •  0
  •   Siva    10 年前

    检查以下步骤

    1. 数据库.SetInitializer(空);-->英寸全球.asax.cs

    2

    1. 检查一下
        22
  •  0
  •   p.campbell    10 年前

    修改 Global.asax.cs ,包括 Application_Start

    Database.SetInitializer<YourDatabaseContext>(
     new DropCreateDatabaseIfModelChanges<YourDatabaseContext>());
    
        23
  •  0
  •   SinghMavi    10 年前

    尝试使用属于using的数据库SetInitializer系统数据实体;

    在全球.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);
        }
    
    }
    
        24
  •  0
  •   Tomino    9 年前

    很奇怪,但这里所有的答案对我来说都没用。

    已将数据库迁移到最新版本

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

    我的来源: https://msdn.microsoft.com/en-us/data/jj591621.aspx#specific

        25
  •  0
  •   Julia Savinkova    8 年前

    当我们将一个数据库用于两个应用程序时,我也遇到了同样的问题。设置 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

        26
  •  0
  •   Tomas Kubes    6 年前

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

    并从OmModelCreating注册:

    public partial class MyDbContext : DbContext
    {
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            Database.SetInitializer<MyDbContext>(new MyDbContextInitializer());
    
            //other code for creating model
        }
    }
    
        27
  •  -3
  •   Milan Goswami    9 年前

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

    1) 打开DbContext文件

    2) 使用添加命名空间Microsoft.AspNet.Identity文件.实体框架;

    public MyDbContext():base(“name=MyDbContext”) 数据库.SetInitializer(新建DropCreateDatabaseAlways());