为什么 EF 说我的模型已经改变而实际上没有?

Why is EF saying my model has changed when it has not?

我不断收到以下错误:

System.InvalidOperationException: The model backing the 'McContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).

我正在使用来自 nuget v6.1.3 的最新 Entity Framework 创建一个 .NET MVC 5 网站。我附加到本地 MDF 文件,因为我没有在本地安装 SQL Server 或 Express。我正在使用 Code First 模型。

我昨天和今天花了几个小时梳理关于这个错误的 SO 和 WWW 帖子,但没有找到有效的解决方案。他们中的大多数围绕不同类型的初始化器,或者关于代码如何首先需要迁移或模型更改的初始化器的简短解释。但是我是运行通过PM控制台手动设置的。我在下面包含了我的步骤。

连接字符串:

<add name="testSQLConnection" connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\jwatts\Documents\Visual Studio 2015\Projects\MyProject\Databases\MyProject01.mdf;Integrated Security=True;Connect Timeout=30" providerName="System.Data.SqlClient" />

型号:

public class Family
{
    public Family() { }

    [Key, Index(IsUnique = true)]
    [Column(Order = 0)]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Required]
    [StringLength(128)]
    public string Name { get; set; }

    [StringLength(1024)]
    public string Description { get; set; }

    public DateTime Created { get; set; }

    public string CreatedBy { get; set; }

    public DateTime? Changed { get; set; }

    public string ChangedBy { get; set; }

    public DateTime? Deleted { get; set; }

    public string DeletedBy { get; set; }
}

上下文:

public class McContext : DbContext
{
    public McContext() : base("testSQLConnection") { }

    public DbSet<Family> Families { get; set; }
}

配置:

internal sealed class Configuration : DbMigrationsConfiguration<Data.McContext>
{
    public Configuration()
    {
        MigrationsDirectory = @"Data\Migrations";
        AutomaticMigrationsEnabled = false;
        AutomaticMigrationDataLossAllowed = false;
    }

    protected override void Seed(McContext context)
    {
        context.Families.Add(new Family()
        {
            Name = "My Family",
            Description = "The family",
            Created = DateTime.Now,
            CreatedBy = "system"
        });
        context.SaveChanges();
    }
}

自动生成迁移 class:

public partial class StartupConfig : DbMigration
{
    public override void Up()
    {
        CreateTable(
            "dbo.Families",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    Name = c.String(nullable: false, maxLength: 128),
                    Description = c.String(maxLength: 1024),
                    Created = c.DateTime(nullable: false),
                    CreatedBy = c.String(),
                    Changed = c.DateTime(),
                    ChangedBy = c.String(),
                    Deleted = c.DateTime(),
                    DeletedBy = c.String(),
                })
            .PrimaryKey(t => t.Id)
            .Index(t => t.Id, unique: true);

    }

    public override void Down()
    {
        DropIndex("dbo.Families", new[] { "Id" });
        DropTable("dbo.Families");
    }
}

单元测试代码:

[TestMethod]
public void CreateTheContext_Test()
{
    using (var ctx = new McContext())
    {
        //error on this line below:
        var fam = ctx.Families.Where(f => f.Name.Contains("My")).FirstOrDefault();
        Assert.IsTrue(fam != null && fam.Name.Contains("My"));
    }   
}

休闲步骤:

  1. 我从 "clean slate" 开始,删除了我测试数据库中的所有数据库 table,并删除了所有 Data\Migrations.
  2. 重建解决方案。 (基础项目和单元测试项目)
  3. 在程序包管理器控制台中,运行“Add-Migration StartupConfig
  4. 迁移文件已添加到 Data\Migrations,名为“{datetime}_StartupConfig.cs”。参见上文 StartupConfig class。
  5. 我构建了项目。
  6. 我运行“Update-Database -TargetMigration:StartupConfig
  7. PM控制台输出4行,包括"Running Seed method",成功完成。
  8. 我通过 SQL 查询确认“__MigrationHistory”和“Families”table 已添加到数据库中,并且每个 table有 1 条记录。
  9. 我运行单元测试并收到错误。

我有一个更复杂的模型,但我开始一个一个地删除东西,使事情尽可能简单。但是我不能比这更简单了,但错误仍然存​​在。值得注意的是,对于这个特定项目,我从未从单元测试中获得成功的查询。

当我在上面输入这些重新创建的步骤时,我同时执行了这些步骤,并且遇到了同样的错误。

我不知道接下来要尝试什么?

因为你是代码,所以它没有改变,它必须与迁移 table(具有你的数据库模型信息的那个)或你正在使用的数据库文件有关。

我会建议安装 Sql server express 并重试一切。由于您正在创建的数据库是一个文件,因此您将面临更多风险。

编辑:

尝试查看您的项目正在使用的实例的名称。默认情况下 EF 使用 DefaultConnection。检查所有项目中的 web.config 或配置文件。

在根据@AaronLS 的建议检查单元测试中的连接字符串时,我发现连接字符串不同。

事实证明,单元测试的 App.config 没有连接字符串并且将 "sqlTestConnection" 视为数据库名称,因为它无法解析它。

将连接字符串添加到 App.config 解决了问题。