实体框架代码优先:如何手动更新数据库?

Mik*_*ike 23 .net sql-server-ce ef-code-first c#-4.0 entity-framework-4.1

我已经构建了一个小型WPF演示应用程序,该应用程序使用EF Code-First将其数据保存在SQL CE 4.0 DB中.除非我从模型对象中删除属性,否则它工作正常.例如,如果我从这个类中删除"HosteBy".....

public class Dinner
{
    public int DinnerID { get; set; }
    public string Title { get; set; }   
    public DateTime EventDate { get; set; }
    public string Address { get; set; }
    public string HostedBy { get; set; }

    public virtual ICollection<RSVP> RSVPs { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

...它抛出了这个异常:

自创建数据库以来,支持'NerdDinners'上下文的模型已更改.手动删除/更新数据库,或使用IDatabaseInitializer实例调用Database.SetInitializer.例如,DropCreateDatabaseIfModelChanges策略将自动删除并重新创建数据库,并可选择使用新数据对其进行种子设定.

即使从数据库中手动删除"HosteBy"字段后,该错误仍然存​​在.我在这里错过了什么?我是否必须删除/截断数据库,还是有其他解决方案?

Chr*_*ini 26

在您更改Code First Model的第一个场景中,在您手动修改数据库之前,答案是打开(Nuget)Package Manager控制台并键入:

update-database -verbose
Run Code Online (Sandbox Code Playgroud)

除了 - 因为在这种情况下你要移除一个列,这将报告它将要删除的东西,并且如果没有明确说明没有,它将不会删除任何内容.所以你输入:

update-database -f -verbose
Run Code Online (Sandbox Code Playgroud)

现在,这将删除模型中的列.-verbose说要向你展示它运行的SQL.如果你害怕只是让它删除东西而不是在运行之前检查SQL,请使用:

update-database -f -script

而是将SQL转储到您可以查看的脚本,并自己手动运行.

如果您继续手动删除数据库中的列,您现在手上有一个更复杂的场景; 此处另一个答案中描述的EdmMetadata表包含整个数据库的哈希,现在与数据库本身不匹配.您可以运行手动SQL,以通过检查之前的内容以及数据库当前的外观,将实体框架预期的方式返回到实际框架预期的方式(手动修改之前的方式,使其与哈希一致).

如果这不可行,那么您现在处于Entity Framework Code First中最丑陋的部分.您需要消除哈希表并将db反向工程为代码文件.

哈希表名称取决于EF的版本.在你想问的旧版EF4中,它被称为EdmMetadata.在较新的EF5中,它被称为__MigrationHistory(如果您正在查看SQL Server Management Studio,则在数据库的系统表下).你需要把它擦掉.

第二步的好消息是将数据库逆向工程化为代码,微软已经发布了一个测试工具,可以为你完成这项工作.

对数据库和EF Power Tools进行逆向工程的演练

您可以跳过其中的许多第一步,因为他们只是设置数据库并添加一些废话,以便他们可以演示您需要做什么:逆向工程数据库.

更新:

使用手动迁移来解决此方案也是可行的.备份数据库,然后运行:

add-migration WhateverYouWantToCallThis
Run Code Online (Sandbox Code Playgroud)

需要运行的db EF Migrations的修改将出现在生成的C#命令中.现在由你来修补它们以解决它试图做的事情(例如试图删除已经删除的列),并实现它将需要的东西(例如添加回来)您在模型中仍然拥有的表,但您在数据库中手动删除了该表.

一旦你添加了这个并运行update-database -f,EF Code First将坚信您已经按照需要的方式更新了数据库,并根据最终结果更新其哈希值.如果您做了正确的更改,现在可以正常进行迁移.如果这仍然导致错误,您通常可以将手动迁移的命令复制到某处并将其删除,从备份中恢复数据库,再次添加手动迁移,然后重试.最糟糕的情况是你采取上面的逆向工程步骤.