2

我正在开发的产品需要支持不同的数据库类型。一开始需要支持SQL ServerOracle,但未来可能需要支持IBM DB2Postgre SQL

并且该产品将需要为可能具有略微不同架构的不同客户工作。例如,一个带有SQL Server的客户端上的列名可能是_ID,而在另一个带有Oracle的客户端上,它可能是I_ID.

除了列名之外,一般模式将是相同的。它们都可能映射到同一个对象。但是,可能会有一些特定于每个客户的额外列。但是,这些不需要映射到对象。可以使用更简单的方式在Master-Detail场景中检索它们。

我想使用 ORM,因为我们需要支持不同类型的数据库提供程序。但据我所知,ORM 不适合在运行时创建映射。

为了支持这些请求(摘要):

  1. 每个客户的列名可能不同,但除了名称之外,它们几乎是相同的列。
  2. 每个客户的数据库提供商可能不同。
  3. 每个客户可能有额外的列。
  4. 编辑:程序应该能够通过在运行时更改配置来支持新数据库。

为此类规范创建数据访问的好方法是什么?有没有办法用 ORM 做到这一点?或者我是否需要编写特定于每个数据库的代码来支持这种情况?我是否有任何其他选择可以比直接使用 ADO.NET 更容易?

编辑:我认为我的问题写得太宽泛了,并没有清楚地解释它,对此感到抱歉。问题是我不会创建数据库。它们将已经创建,并且程序应该能够通过在运行时配置程序来使用新数据库。我无法控制数据库。

另一件事是,当然可以通过在程序中创建SQL语句来实现,但这确实很麻烦。所有这些提供程序都有稍微不同的规则和不同的 SQL 实现,所以工作量很大。我想知道是否可以使用 ORM 之类的东西来让我更轻松。

编辑 2:我完全意识到这是一种愚蠢的做事方式,它显示了糟糕的设计决策。但是我花了很多时间试图说服我的公司不要这样做。他们不想改变自己的思维方式,因为实习生会这样告诉他们。所以任何帮助将不胜感激。

4

1 回答 1

0

每个客户的列名可能不同,但除了名称之外,它们几乎是相同的列。

由于仅此要求,您将不得不自己动态构建 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 语句。但是开始吧,如果您对此有具体问题,请创建一个新问题,添加您已有的代码,并让我们知道您在哪里遇到了问题。

每个客户的数据库提供商可能不同。

在这里,您将需要使用像Dapper这样的东西,因为它适用于 POCO 类(就像您将要构建的那样),而且它还只是扩展了接口,因此您使用什么具体类(例如or )IDbConnection并不重要,它的工作原理相同。SqlConnectionOracleConnection

每个客户可能有额外的列。

这实际上非常简单。利用表中的IsCustom字段CustomerDataTableField将这些字段添加到动态构建的 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类,这些类只为正确的客户安装。现在你有一堆小的、客户特定的系统扩展,它们很容易开发、安装和维护。

于 2013-05-29T12:14:43.000 回答