我构建了一个小型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; }
}
...它抛出了这个异常:
自创建数据库以来,支持'NerdDinners'上下文的模型已更改。手动删除/更新数据库,或使用IDatabaseInitializer实例调用Database.SetInitializer。例如,DropCreateDatabaseIfModelChanges策略将自动删除并重新创建数据库,并可选择使用新数据对其进行播种。
即使从数据库中手动删除字段“HosteBy”,错误仍然存在。我在这里错过了什么?我是否必须删除/截断数据库,还是有其他解决方案?
答案 0 :(得分:25)
在您更改Code First Model的第一个场景中,在您手动修改数据库之前,答案是打开(Nuget)Package Manager控制台并键入:
update-database -verbose
除了 - 因为在这种情况下你要移除一个列,这将报告它将要删除的东西,并且如果没有明确说明没有,它将不会删除任何内容。所以你输入:
update-database -f -verbose
现在,这将删除模型中的列。 -verbose
说要向您展示它运行的SQL。如果你害怕只是让它删除东西而不是在运行之前检查SQL,请使用:
update-database -f -script
而是将SQL转储到您可以查看的脚本,然后自己手动运行。
如果你继续手动删除了数据库中的列,那么现在你手上有一个更复杂的场景;此处另一个答案中描述的EdmMetadata表包含整个数据库的哈希,现在与数据库本身不匹配。您可以运行手动SQL,以便按照Entity Framework预期的方式(通过手动修改它之前的方式,使其与哈希一致)恢复数据库,方法是检查之前的内容以及数据库当前的状态。
如果这不可行,您现在处于Entity Framework Code First中最丑陋的部分。您需要消除哈希表并将数据库反向工程为代码文件。
哈希表名称取决于EF的版本。在你想问的旧版EF4中,它被称为EdmMetadata。在较新的EF5中,它被称为__MigrationHistory(如果您正在查看SQL Server Management Studio,则在数据库的系统表下)。你需要把它擦掉。
第二步的好消息是将数据库反向设计为代码,微软已经发布了一个测试工具,可以为你做这个。
Walk-through of reverse-engineering a db, and EF Power Tools
你可以跳过那里的许多第一步,因为他们只是设置一个数据库并为它添加一些废话,以便他们可以演示你需要做什么:逆向工程数据库。
使用手动迁移来解决此问题也是可行的。备份数据库,然后运行:
add-migration WhateverYouWantToCallThis
需要运行的db EF Migrations的修改将出现在生成的C#命令中。现在由你来修补它们以解决它试图做的事情(例如试图删除已经删除的列),并实现它将需要的东西(例如添加回来)您在模型中仍然拥有的表,但您在数据库中手动删除了该表。
一旦你添加了这个并运行update-database -f
,EF Code First就会坚信您已经按照需要的方式更新了数据库,并根据最终结果更新其哈希值。如果您做了正确的更改,现在可以正常进行迁移。如果这仍然导致错误,您通常可以将手动迁移的命令复制到某处并将其删除,从备份中恢复数据库,再次添加手动迁移,然后重试。最糟糕的情况是你采取上面的逆向工程步骤。
答案 1 :(得分:3)
看看
第5步:更改我们的模型
答案 2 :(得分:2)
如果您的数据库包含一些名为EdmMetadata
的奇怪表,则您的上下文使用一些非常基本的数据库版本控制级别。当它创建数据库时,它会将模型的哈希存储到此表中,并且每次为应用程序构建模型时(第一次在重新启动应用程序后使用上下文)它再次计算哈希并将其与存储在中的哈希进行比较。那张桌子。这意味着模型中的任何更改都将导致不同的哈希值,EF将对您看到的异常做出反应。手动更改数据库对您没有帮助,因为该表还包含旧的。
解决方案是:
IncludeMetadataConvention
。DbCompiledModel.ModelHash
表中。EdmMetadata
- 如果更改模型,它将自动删除数据库并创建一个新数据库 - 您将丢失所有数据答案 3 :(得分:0)
查看本文的“使用现有数据库进行代码优先迁移”一节 http://msdn.microsoft.com/en-us/data/dn579398
有时您的项目和数据库可能会失去同步。 因此,您可能必须根据现有数据库重新同步模式。
1)基于现有模式创建迁移:
添加迁移InitialCreate
2)之后运行Update-Database将条目添加到_MigrationsHistory表中,以指示迁移已完成,直到现有模式。
答案 4 :(得分:0)
在使用Code First时需要记住三件简单的事情
一切都是自我解释的。
您需要手动在Package Manager控制台上运行这些命令。 我迟到了,但希望能有所帮助