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

265

错误信息如下:

"自数据库创建以来,'AddressBook'上下文所支持的模型已更改。请手动删除/更新数据库,或使用IDatabaseInitializer实例调用Database.SetInitializer。例如,RecreateDatabaseIfModelChanges策略将自动删除和重新创建数据库,并可选择性地填充新数据。"

我正在尝试使用Code-First功能,以下是我编写的内容:

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”,当我尝试将联系人对象添加到上下文时发生错误。这里有什么遗漏吗?


1
从您的数据库中删除 __MigrationHistory 表。 - Zahid Hasan
1
@ZahidHasan 绝对不要删除 __MigrationsHistory 表,除非您完全理解 __MigrationsHistory 的目的,并愿意手动协调代码和数据库之间的差异,并在生产环境中进行相同的更改。 - Aaron Queenan
27个回答

2

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


2

我曾经遇到这个问题,结果发现一个项目指向了SQLExpress,但有问题的那个项目指向了LocalDb(分别在它们各自的web.config文件中)。这是一个愚蠢的疏忽,但值得在这里注意,以防其他人出现类似问题时进行故障排除。


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

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>

我们遇到了与Newtonsoft.json版本相似的问题,当我们更新版本时,问题得到了解决。 - Rui Estreito

1
这个错误可能表示您的连接字符串存在问题,以及您的连接字符串名称是否与数据库上下文声明相匹配。
我之所以出现这个错误,是因为我错误地命名了本地数据库(愚蠢的错误),而web.config中的连接字符串名称“DefaultConnection”与MyDbContext不匹配。
public MyDbContext(): base("DefaultConnection")
{}


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

这应该是被接受的答案!!其他人的回答浪费了我一个小时的时间,只有这个几乎不需要改变任何东西就解决了错误信息。 - AndrewBenjamin

1
良好的建议,但并非在所有情况下都准确。我找到了一个解决方法。 请确保使用Visual Studio中的PM窗口运行"enable-migrations",并将Migration文件夹添加到您的项目中。
确保两个C#类文件添加到该文件夹中,其中包含所有模型及其各自的属性。
如果您已经完成上述步骤,请构建解决方案并发布以进行部署。
逻辑是现有元数据无法被覆盖,因为您的应用程序没有元数据来替换当前元数据。因此,您会收到此错误消息:"The model backing the context has changed since the database was created"。

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

        }

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

0

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

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


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/zh-cn/data/jj556606.aspx


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接