首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实体框架-架构升级、多DBMS和代码优先

实体框架-架构升级、多DBMS和代码优先
EN

Stack Overflow用户
提问于 2011-04-03 06:01:47
回答 2查看 921关注 0票数 2

我正在研究如何在即将到来的项目中使用微软的实体框架,该项目是一个现有产品的点发布版。我们目前的产品支持两个DBMS (Oracle和Server),每个数据库的模式都在单独的.sql脚本文件中维护。

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

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

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

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-04-03 09:47:20

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

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

EF本身目前不支持升级现有DB。在使用EDMX时,数据库生成过程要么由T4模板控制,要么由工作流控制,这样就可以定制数据库,并且已经有了单独的特性,称为实体设计数据库生成电源包,它允许以模型优先的方式增量地构建数据库。问题是,这个特性正在使用VS数据库工具。我认为这些工具只适用于SQL server。我从来不喜欢这些自动化工具,所以我仍然认为数据库升级应该通过一些工具来手动控制,以获得当前和最后部署的数据库版本之间的不同脚本。只有在将新版本部署到生产环境中时,才需要diff脚本。在测试和开发环境中,始终可以重新创建整个数据库。

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

编辑:

基于@Tridus的答案,我只是补充说,您可以先创建数据库,然后使用EF4.1中的fluentAPI来映射它们。您的数据库必须具有完全相同的模式(表名、列名等),它们不能使用任何特定的特性(我希望序列不会成为问题,因为这只是Oracle处理自动增量列的方式)。

票数 2
EN

Stack Overflow用户

发布于 2011-04-03 10:44:22

实际上,对于数据库第一次设计来说,这是相当可行的,但是由于数据库处理事情的方式不同,您将无法轻松地处理这些问题。

  • 序列是一个(因为EF完全忽略了它们)。您可以在Oracle中通过在Insert上填充它的表上放置一个触发器来伪造它,但我还发现,如果以后必须更新模型,那么EF“忘记”该列是一个标识列,它将再次尝试在其中添加一个0。我还发现,在Oracle中,如果使用触发器,尝试获取新ID是不可靠的。在执行插入之前,我们只是从序列中选择并设置对象上的ID,因为在Oracle中通常是这样做的。您还可以使用处理它的存储过程。
  • 数字的处理方式不一样。Server使用映射到Int32、Int64等的数字格式。Oracle的数字格式完全不同,Server中的全范围Int32是Oracle中的一个数字(10,0)。它实际上是EF中的Int64,因为它比Int32大。我还发现,甲骨文的EF提供商很喜欢使用Decimal,即使它不必这么做,但这可能只是一个测试版问题。
  • Oracle中的存储过程需要将一些值放在app.config/web.config中,以便在EF中工作。我不确定这是否只是Server中的混乱,还是会导致问题。

最后,EF代码首先是非常不成熟的,根据docs的说法,它不支持在这个版本中更改数据库结构。我不确定Oracle的提供者是否也支持它(它可能,还没有尝试过)。

大部分这些都是您可以处理的内容,但是您需要做一些工作来将差异隐藏在代码的其余部分中,并且可能需要一个包装层来完成。

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5527886

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档