如何创建支持多个数据库的应用程序

Posted

技术标签:

【中文标题】如何创建支持多个数据库的应用程序【英文标题】:How to create an application supporting multiple databases 【发布时间】:2016-06-03 10:41:37 【问题描述】:

我有一种情况,我需要创建一个支持多个数据库的应用程序。多数据库意味着客户端首先可以使用任何数据库,如Oracle、SQL Server、mysql、PostgreSQL。

我试图使用像 NHibernate 或 MyBatis 这样的 ORM。但他们有其局限性,需要专业知识才能使用。

所以我决定使用 Microsoft 提供的 Data Providers,例如 ADO.NET、OLEDB、ODP.NET 等。

有什么办法可以让我的数据库逻辑对所有数据库都保持一致?我已经尝试过IDbConeectionIDbCommand 等,但在 Oracle(参考光标)的情况下它们会出现问题。

我有什么办法可以做到这一点?一些链接或指南将不胜感激。

编辑:DBType 存在问题,因为它们是枚举定义不同的数据提供者。

【问题讨论】:

您是否考虑过使用实体框架代码优先方法? @JCM Entity 对 oracle 版本的支持不好。 我认为你最好的选择仍然是使用像实体框架这样的 ORM。是的,他们有局限性,是的,他们需要专业知识(虽然不是太多),但谁说支持多个数据库会很容易?在复杂的情况下,您可能会使用存储过程或只是根据当前提供程序有条件地执行代码(但仅限于复杂情况下)。 我建议您继续使用 nHibernate,因为它最适合 Oracle,并且它是大多数 Web 应用程序最推荐的 ORM。它还可以帮助您避免处理特定于数据库的查询的麻烦。一旦您熟悉了它,它将成为您使用 Query Builder 组合域语言的强大工具。你说它有限制,你能告诉我们一些影响你考虑的限制吗? EF 在 Oracle 中运行良好,但仍然使用托管驱动程序... 【参考方案1】:

嗯,现实生活中的应用程序就是这样复杂的。在不知不觉中,您想用 App 替换 UI,将您的逻辑公开为 WCF 服务,用另一个服务提供商更改电子邮件服务,在模拟 DAL 的同时测试您的代码片段,并用另一个更改数据库.

处理这个问题的常用方法是通过一个将实现与调用者分开的接口传递所有调用。之后,您可以实现不同的 DAL。

我个人通常采用这种方法:

首先创建一个包含所有接口的 DLL。基本上,这个想法是通过界面公开您的 UI、应用程序或任何需要的所有调用。从现在开始,您的 UI 不再与数据库或电子邮件提供商对话。 如果您需要访问界面,请使用工厂模式。永远不要使用“新”;从长远来看,这会给你带来麻烦。 创建它并非易事,需要适当的制作。通常我从最低版本开始,将 UI 中的所有其他内容作为第一个版本进行修改,然后在创建界面的同时将所有涉及数据库或服务的内容移动到正确的项目中,最后重新设计所有内容,直到我 100% 满意. 接口应经久耐用。当然,随着时间的推移会发生变化,但你真的想尽量减少这些。想想未来会怎样,阅读其他人的想法,并确保你的界面反映了这一点。

基本上,您现在拥有一个可与单个数据库、邮件提供商等一起使用的工作软件。到目前为止一切都很好。

接下来,重新设计工厂。基本上,您希望使用配置设置为您的数据选择正确的提供程序(实现您的接口的正确 DLL)。大多数情况下,一个简单的开关就足够了。

在这一点上,我通常养成为接口进行大量单元测试的习惯。

最后一步是为不同的数据库提供程序创建 DLL。其中之一将在您的应用程序运行时加载。

我更喜欢简单的 Linq 而不是 SQL(我也使用 LinqConnect 的库),因为它非常快。我只是从复制粘贴另一个数据库提供程序开始,然后重新设计它直到它工作。就我个人而言,我不再相信神奇的“支持所有 sql 数据库”解决方案:根据我的经验,某些数据库处理某些查询的速度比其他数据库快得多 - 这意味着您最终可能会得到一些自定义代码反正每个数据库。

这也是您的单元测试真正获得回报的地方。基本上,您可以从复制粘贴开始并进行测试。如果幸运的话,一切都会立即以良好的性能运行...如果没有,您知道从哪里开始。

经久耐用

打造经久不衰的东西。事情会改变:

考虑更新并对其进行测试。更喜欢自动测试。 您不想每天都在修补您的工厂。使用反射、表达式、代码生成或任何你的毒药来省去更改代码的麻烦。 花时间编写测试。确保覆盖大部分。这一点我怎么强调都不为过;在压力下,人们通常不写测试来“节省”时间。您会注意到,这一次您的“保存”将在您上线后加倍支持您。每个月。

实体框架呢

我看到很多客户因此而在性能方面遇到麻烦。在我测试它的许多次中,我有同样的经历。我注意到客户围绕 EF 进行大量查询以获得一些不错的性能。

公平地说,我几年前就放弃了,我知道他们已经取得了相当大的性能改进。不过,我会在考虑之前对其进行测试(尤其是复杂查询)。

如果我会使用 EF,我会在“数据库公用 DLL”中实现所有 EF 内容,然后从中派生类。正如我所说,并非所有数据库都与查询相同 - 您可能希望实施一些获得良好性能所必需的技巧。你的测试会告诉你。

奖金

通过接口编程的其他原因与代理的结合有很多优势。仅举几例,您可以通过简单地实现相同的接口轻松创建日志接收器、缓存、统计信息、WCF 等。如果有一天你讨厌你当前的 OR 映射器,你可以把它扔掉,而不用触及应用程序的任何一行。

【讨论】:

你还这么认为吗? 虽然 EF 在过去 3 年的性能确实变得更好,但我刚刚再次阅读了这篇文章,是的,我相信这仍然成立。为了使其实用,这不仅仅是理论:我们目前的代码库不到 100 万行代码。如果不通过接口分离代码并编写大量单元测试,那根本不可能。【参考方案2】:

我相信 Microsoft 的数据访问组件会适合您。 https://en.wikipedia.org/wiki/Microsoft_Data_Access_Components

【讨论】:

自 11 年以来就没有工作过,并且不支持现代操作系统,所以我不推荐这个。但是,我自己不知道在这种情况下什么是合适的。【参考方案3】:

如何编写微服务并使用 rest api 连接它们? 你(也许你的团队)可以提供一个处理逻辑和用户界面的核心应用程序。这仍然基于您当前的技术。但是,您可以提供多种类型的微服务(基于 asp.net 或 core),而不是直接添加某种数据库连接,从而提供一个 rest api。您可以从此类微服务中的每个数据库中获取数据。因此,您将开发 1 个微服务,例如MySQl 和另一个用于 MsSQL 的,当新客户提出 oracle 时,您编写一个新的小型微服务来处理您预期的 API。

更多信息(基于 .net 核心)在这里:https://docs.asp.net/en/latest/tutorials/first-web-api.html

我认为这是一个团队讨论,您决定使用哪种技术。但今天我建议写一个微服务。它使新应用程序的附件例如移动设备也容易得多:)

【讨论】:

【参考方案4】:

是的,这是可能的。

现在我的所有逻辑相关数据(通常您可以调用元数据)都驻留在一个数据库中,而日期驻留在另一个数据库中。

你需要做什么。您应该在两个不同的文件中有连接相关参数,或者您可以将这些文件称为道具文件。现在你需要有连接具体类,它从这些道具文件中获取参数。因此,您需要创建连接的地方只需提供道具文件,它将根据需要创建数据库连接。

【讨论】:

以上是关于如何创建支持多个数据库的应用程序的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 abp 创建 module 并应用单独的数据库迁移

我需要多个持久性商店吗?

调整文本以支持多个屏幕

如何从现实世界中的多个队列中读取?

如何在 Rider 中支持多个应用程序配置

如何在java中为不同的数据库创建多个数据库连接