2

我正在考虑在即将推出的项目中使用 Microsoft 的实体框架,该项目是现有产品的点发布。我们当前的产品支持两个 DBMS(Oracle 和 SQL Server),每个的架构都保存在单独的 .sql 脚本文件中。

实体框架 (4.1) 看起来很吸引人,因为它允许通过代码生成、反射等自动实现各种场景。但是,据我所知,其中一些好处似乎是相互排斥的。

例如,为了支持多个 DMBS,我推断我需要使用模型或代码优先设计,在这种情况下,EF 将根据模型为每个 DMBS 生成模式(我几乎没有看到关于此的帖子或文档,所以我可能是错的)。这意味着我们现有的模式需要被放弃(模型优先)或映射(代码优先)。此外,更新架构需要手动脚本,因为 EF 似乎不支持架构升级(不清除数据)。

  1. 模型优先和代码优先是在 EF 中支持多个 DBMS 的唯一可行方法吗?我意识到从技术上讲,不可能保证两个任意模式是相同的,所以我认为这是真的。
  2. 代码优先和映射到多个 DBMS 系统是否存在任何潜在缺陷?例如,Oracle 没有自增列;你必须使用序列。这在 DbContext 中是如何映射的?我需要为每个 DBMS 创建单独的映射吗?
  3. EF 是否支持将现有 DBMS 模式升级到代表 EF 模型的任何机制(模式重新创建 =/= 升级),或者我是否仅限于手动执行此操作?
  4. 我确实想出了一种可能的方法来首先使用数据库并支持多个 DBMS,但这是维护的噩梦。这个想法是为两个生成的数据模型添加另一层抽象,并为每个 EF 生成的模型创建转换器类。这似乎是最好的方法,这样每个 DBMS 都可能有自己的模型,但我的代码将处理映射。但在这样做的过程中,我真正从 EF 中获得了什么?也许查询生成,但这值得吗?
4

2 回答 2

2

实际上,模型优先和数据库优先都有相同的约束。这两种方法都使用一个 EDMX 文件,其中包含与单个数据库提供者直接相关的 SSDL(存储 = 数据库层的描述)部分,因此如果您想拥有两个不同的数据库提供者,您必须拥有两个不同的 SSDL 部分并将它们保存在同步。您可以使用单个 CSDL(概念层的描述 = 您的模型类)和单个或两个 MSL(SSDL 和 CSDL 之间映射的描述 - 仅当表和列在两个 SSDL 中具有完全相同的名称时才可能使用单个文件)。我知道 EDMX 文件只能由单个 SSDL、CSDL 和 MSL 部分组成,所以我希望设计人员不支持这种情况,您将不得不手动修改第二个 SSDL 或使用两个 EDMX = 模型每个更改两次。

代码优先的方法可以使这变得更简单,但问题是 Oracle 提供程序在使用代码优先和数据库生成时有多好。在自动递增列的情况下,提供者负责正确解释所需的功能,例如序列。

EF 本身目前不支持升级现有数据库。使用 EDMX 时,数据库生成过程由 T4 模板或工作流控制,因此可以自定义,并且已经有单独的功能称为实体设计器数据库生成电源包它允许使用模型优先的方法增量构建数据库。问题是此功能使用的是 VS 数据库工具。我认为这些工具只适用于 SQL 服务器。我从不喜欢这些自动化工具,所以我仍然认为应该在一些工具的帮助下手动控制数据库升级,以获取当前和上次部署的数据库版本之间的差异脚本。只有在将新版本部署到生产环境时才需要 diff 脚本。在测试和开发环境中,您始终可以重新创建整个数据库。

使用两个 EDMX 模型时应该不需要抽象。模型必须产生相同的概念层。在这种情况下,您只需要一组按约定映射的 POCO 类(与实体相同的类名,具有相同类型和可访问性的相同属性),因此它们将适用于两种模型。

编辑:

根据@Tridus 的回答,我只是补充说您可以先创建数据库并使用 EF 4.1 中的 fluentAPI 来映射它们。您的数据库必须具有完全相同的架构(表名、列名等),它们不能使用任何特定功能(我希望序列不会成为问题,因为这正是 Oracle 处理自动递增列的方式)。

于 2011-04-03T09:47:20.223 回答
1

对于数据库优先的设计,这实际上是相当可行的,但是由于数据库处理事情的方式不同,有些警告您将无法轻松解决。

  • 序列是一个(因为它们完全被 EF 忽略了)。您可以在 Oracle 中通过在插入时填充它的表上放置一个触发器来伪造它,但我还发现,如果您必须稍后更新模型,那么 EF “忘记”该列是一个标识列,它会尝试再次将 0 插入其中。如果您使用触发器,我还发现在 Oracle 中尝试获取新 ID 是不可靠的。我们只是在执行插入之前从序列中选择并在对象上设置 ID,因为这就是您通常在 Oracle 中执行的方式。您还可以使用处理它的存储过程。

  • 数字的处理方式不同。SQL Server 使用映射到 Int32、Int64 等的数字格式。Oracle 的数字格式完全不同,SQL Server 中的全范围 Int32 是 Oracle 中的 Number(10,0) ...实际上是 EF 中的 Int64,因为它是比 Int32 大。我还发现 Oracle 的 EF 提供程序非常喜欢使用 Decimal,即使它不是必须的,但这可能只是一个测试版问题。

  • Oracle 中的存储过程需要在 app.config/web.config 中放入一些值才能在 EF 中工作。我不确定这是否会在 SQL Server 中变得混乱,或者是否会导致问题。

最后,EF Code First 非常不成熟,根据文档不支持在此版本中更改数据库结构。我不确定甲骨文的供应商是否也支持它(它可能,没有尝试过)。

其中大部分是您可以解决的问题,但是您需要做一些工作来隐藏与其余代码的差异,并且可能需要一个包装层来做到这一点。

编辑 - 关于你的 #4 - EF 4.1 可以生成部分 POCO 类。您可以创建另一个在更新模型时不会重新生成的部分类代码文件,然后添加隐藏差异的属性/方法,而不是围绕每个生成的模型编写包装器来隐藏任何差异。您的应用程序代码只需要注意使用它们,它们就会处理问题(就像我提到的数字问题一样,您可以使用另一个可以为 Oracle 进行必要转换的属性完全隐藏它)。

于 2011-04-03T10:44:22.260 回答