创建对可能更改的模式的数据访问

时间:2013-05-29 11:58:28

标签: c# .net database orm ado.net

我正在处理的产品需要支持不同的数据库类型。首先,它需要支持 SQL Server Oracle ,但将来它可能需要支持 IBM DB2 Postgre SQL

该产品需要为可能略有不同架构的不同客户提供服务。例如,一个客户端上 SQL Server 的列名可能是_ID,而另一个 Oracle 的客户端上的列名可能是I_ID

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

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

支持这些请求(摘要):

  1. 每个客户的列名可能不同,但除了名称之外,它们几乎是相同的列。
  2. 每个客户的数据库提供商可能不同。
  3. 每位客户可能都有额外的列。
  4. 编辑:程序应该能够通过在运行时更改配置来支持新数据库。
  5. 为此类规范创建数据访问的好方法是什么?有没有办法用ORM做到这一点?或者我是否需要编写特定于每个数据库的代码来支持这种情况?我是否有任何其他选项可以比直接使用ADO.NET更容易?

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

    另一件事是,当然可以通过在程序中创建SQL语句来实现,但这真的很麻烦。所有这些提供程序具有略微不同的规则和不同的SQL实现,因此它需要做很多工作。我想知道我是否可以使用像ORM这样的东西让我更容易。

    编辑2:我完全清楚这是一种愚蠢的做事方式,它显示了糟糕的设计决策。但我花了这么多时间试图说服我的公司不这样做。他们不想改变他们的思维方式,因为实习生告诉他们。所以任何帮助都会受到赞赏。

1 个答案:

答案 0 :(得分: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
)

存储字段的基本名称。您只需选择一个模式并将其命名为 baseline 。这就是这两个表中的内容。然后你有一个这样的表:

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类(就像你将要构建的那样),它也只是扩展了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类,这些类只为正确的客户安装。现在,您拥有一系列针对系统的小型客户特定扩展,并且可以轻松开发,安装和维护这些扩展。