我正在开发的产品需要支持不同的数据库类型。一开始需要支持SQL Server和Oracle,以后可能需要支持IBM DB2和Postgre SQL .
并且该产品需要适用于架构可能略有不同的不同客户。例如,一个 SQL Server 客户端上的列名可能是 _ID
,而在另一个 Oracle 客户端上,它可能是 I_ID
.
除列名外,一般架构是相同的。它们都可能被映射到同一个对象。 但是,可能会有一些特定于每个客户的额外列。这些不需要映射到对象。可以使用更简单的方法在 Master-Detail 场景中检索它们。
我想使用 ORM,因为我们需要支持不同类型的数据库提供程序。但据我所知,ORM 不适合在运行时创建映射。
为支持这些请求(摘要):
- 每个客户的列名称可能不同,但除了名称之外它们几乎是相同的列。
- 每个客户的数据库提供商可能不同。
- 每个客户可能有额外的列。
- 编辑:程序应该能够通过在运行时更改配置来支持新数据库。
为此类规范创建数据访问的好方法是什么?有没有办法用 ORM 做到这一点?或者我是否需要编写特定于每个数据库的代码来支持这种情况?我是否有任何其他选项比直接使用 ADO.NET 更容易?
编辑:我觉得我的问题写得太笼统了,没有解释清楚,对此深表歉意。问题是我不会创建数据库。它们将已经创建,并且程序应该能够通过在运行时配置程序来使用新数据库。我无法控制数据库。
另外一点,当然可以通过在程序中创建SQL语句来实现,但是那实在是太麻烦了。所有这些提供商的规则和 SQL 实现都略有不同,因此工作量很大。我想知道我是否可以使用 ORM 之类的东西来简化我的工作。
编辑 2: 我完全意识到这是一种愚蠢的做事方式,它表明了错误的设计决策。但我花了很多时间试图说服我的公司不要这样做。他们不想因为实习生这样告诉他们而改变自己的思维方式。因此,我们将不胜感激。
最佳答案
Column names may be different for each customer, but they pretty much the same columns except names.
仅由于这一要求,您就必须自行动态构建 SQL 语句,但这确实非常简单。我建议构建一个这样的表:
CREATE TABLE DataTable (
ID INT PRIMARY KEY NOT NULL,
Name SYSNAME NOT NULL
)
将所有表存储在数据库中。然后像这样构建一个:
CREATE TABLE DataTableField (
ID INT PRIMARY KEY NOT NULL,
DataTableID INT NOT NULL,
Name SYSNAME NOT NULL
)
存储字段的基本名称。您只需选择一个架构并将其称为基线。这就是那两个表中的内容。然后你有一个这样的表:
CREATE TABLE Customer (
ID INT PRIMARY KEY NOT NULL,
Name VARCHAR(256) NOT NULL
)
存储您使用该产品的所有唯一客户,最后是这样的表格:
CREATE TABLE CustomerDataTableField (
ID INT PRIMARY KEY NOT NULL,
CustomerID INT NOT NULL,
DataTableFieldID INT NOT NULL,
Name SYSNAME,
IsCustom BIT
)
为每个客户存储不同的字段名称。我们将在一分钟内讨论 IsCustom
。
现在您可以利用这些表来动态构建您的 SQL 语句。在 C# 中,您可能会在应用程序首次加载时预先缓存所有这些数据,然后使用这些数据结构来构建 SQL 语句。但是开始吧,如果您对此有具体问题,请创建一个新问题,添加您已有的代码,并让我们知道您在哪里遇到问题。
Database provider may be different for each customer.
在这里你需要使用类似 Dapper 的东西因为它与 POCO 类一起工作(就像你将要构建的那样)并且它也只是扩展了 IDbConnection
接口(interface)所以你使用什么具体类并不重要(例如 SqlConnection
或 OracleConnection
),它的工作原理是一样的。
There may be extra columns for each customer.
这其实很简单。利用 CustomerDataTableField
表中的 IsCustom
字段将这些字段添加到动态构建的 SQL 语句中。这解决了数据库方面的问题。现在,为了解决类方面的问题,我建议您利用 partial
类。所以考虑这样一个类:
public partial class MyTable
{
public int ID { get; set; }
public string Field1 { get; set; }
}
代表基线 架构。现在,除标记为 IsCustom
的字段外,所有内容都映射到这些字段中,因此我们需要对这些字段进行一些处理。好吧,让我们为这个类构建一个扩展:
public partial class MyTable
{
public string Field2 { get; set; }
}
因此,现在当您构建一个 new MyTable()
时,它将始终具有这些附加字段。 但是,您不希望每个客户都这样,对吗?好吧,这就是我们使用 partial
类的原因,您在外部程序集中定义这些 partial
类,只为正确的客户安装。现在您拥有了一系列小型的、客户特定的系统扩展,并且它们很容易开发、安装和维护。
关于c# - 创建对可能变化的模式的数据访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16813271/