如何检查数据库模式是否与Entity Framework模式匹配?

23

令我惊讶的是,使用CreateDatabaseIfNotExists上下文初始化程序后,该行代码

context.Database.Initialize(true)

如果模式与我的Code First模式不匹配,EF不会抛出异常。

是否有一种方法可以在尝试访问实体之前验证当前数据库是否与我们的模式匹配,例如,表不再存在于数据库中,EF会抛出异常?


2
现在可以使用 https://github.com/reckface/EntityFramework.Verify 来实现这个目的,该项目由 @reckface 维护。 - user326608
1
现在比永远不做好!太糟糕了,我不再使用EF了 :) - Eduardo Brites
1
在2020年末,有没有官方且简单的方法来检查这个问题? - Nico
3个回答

24

您可以调用CompatibleWithModel方法来确定数据库是否与模型匹配。如果将参数设置为true,则如果在数据库中未找到模型数据,它将引发异常。

bool isCompatible = context.Database.CompatibleWithModel(true);

1
抛出的异常类型是什么? - Jerther
1
我已经检查了EF内部,似乎在数据库中没有元数据的情况下会抛出NotSupportedException异常。 - Alexander
2
作为一条注释,我尝试在一个数据库优先的应用程序上使用它,但它只能与Code-first数据库一起使用。不过还是谢谢你。 - Laki Politis
14
FYI,这似乎已在EF Core中删除:\ 有人知道在EF Core中是否有替代品吗? - pbristow
我不确定这个程序真的检查了数据库结构。我认为它比较的是EF元数据,而不管实际的DB结构。这更像是检查代码模型是否与应用的最后一次迁移保持更新(如果有的话)。 - Dave Cousineau
显示剩余2条评论

8

每次启动应用程序时,EF 不会将数据库模式与模型进行交叉检查。相反,它会寻找保存在数据库中的模型(__MigrationsHistory 表和 EdmMetadata 之前)并将此已保存的模型与您正在使用的模型进行比较。如果模型匹配,则使用数据库。如果模型不匹配,则会抛出异常。如果您的数据库既没有 __MigrationHistory 表也没有 EdmMetadata 表,则 EF 将默认您正在使用 DbContext 的基于数据库优先的方法,并且您的数据库与模型匹配。如果要将数据库与模型进行比较,可以对模型进行 Edmx 转储(使用 EdmxWriter.WriteEdmx),然后使用 Visual Studio 和 EF 设计器从数据库获取 Edmx 并比较 SSDL 部分。


EF会假设您使用带有DbContext的数据库优先方法,并且您的数据库与模型匹配。所以每次我的应用程序启动时,我都需要检查数据库中是否存在所有表和所有列吗? - Eduardo Brites
3
如果您既不更改模型也不更改数据库,并且它们之前匹配,那么您可能不需要这样做。我认为无论您使用哪种访问技术,这个问题都存在,因此开发过程应该注意这一点。在运行时重新发现数据库对我来说似乎是一种错误的方法。 - Pawel
4
@Pawel,你似乎还没有发货!客户安装产品1.0,然后你对其进行更新,这需要进行数据库更改。然后客户安装新代码但无法正确更新架构(无论出于什么原因),然后他们运行产品,当代码尝试读取缺失列时,你会得到一个恶意异常。所以最好先检查,或者至少尝试一些验证,这样你就可以弹出更好的错误消息,然后退出。 - gbjbaanb
1
如果您的应用程序由多个dll组成,每次启动应用程序之前都会检查它们是否存在吗?由于某种原因,在部署应用程序时可能会缺少其中一个dll,从而导致出现令人讨厌的异常。在我看来,您所描述的情况类似 - 您未能正确安装应用程序。一旦应用程序正确安装(即所有dll都已放置并且数据库已正确更新),缺少检查是否是问题?实际上 - 您将如何处理此类检查?如果更改了列类型,长度,索引或添加新表,该怎么办? - Pawel
2
@Pawel 这个框架真的应该处理这种检查,因为它有所有可用于与EDMX数据库进行比较的信息。我还会认为,在运行时加载多个DLL的应用程序在尝试使用它们之前应该检查它们是否存在;一个带有缺失文件和获取位置说明的FileNotFoundException比由于找不到文件而导致代码继续执行的NullReferenceException更有用。 - Matt Arnold

5
有两个工具可以做到这一点。第一个工具非常流行并得到高度发展:
开发人员的解释:https://www.thereformedprogrammer.net/ef-core-taking-full-control-of-the-database-schema/
正如您所看到的,开发人员自己的解释包括对 Code-First、Database-First 和 SQL-First 方法的全面概述。他讨论了所有方法的优缺点,并展示了为什么需要使用 Schema Compare 工具来使用 SQL-First 方法。
Github 项目链接:https://github.com/JonPSmith/EfCore.TestSupport/wiki/9.-EfSchemaCompare 还有一个不太知名的第二个工具,由上面的另一个评论者提到:
https://github.com/reckface/EntityFramework.Verify
第二位开发人员还建议使用 DbUp,该工具提供了一个哲学文章,我认为值得一读,介绍了为什么“微软式”的 Code-First 和 Database-First 方法存在问题,以及将数据库更改视为状态系统的想法可能是一个糟糕的选择。
https://dbup.readthedocs.io/en/latest/philosophy-behind-dbup/

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