我正在处理的产品需要支持不同的数据库类型。首先,它需要支持 SQL Server 和 Oracle ,但将来它可能需要支持 IBM DB2 和 Postgre SQL
该产品需要为可能略有不同架构的不同客户提供服务。例如,一个客户端上 SQL Server 的列名可能是_ID
,而另一个 Oracle 的客户端上的列名可能是I_ID
。
除列名外,通用架构将相同。它们都可能被映射到同一个对象。 但,可能会有一些特定于每个客户的额外列。但这些不需要映射到对象。可以使用更简单的方法在 Master-Detail 场景中检索它们。
我想使用ORM,因为我们需要支持不同类型的数据库提供程序。但据我所知,ORM并不适合在运行时创建映射。
支持这些请求(摘要):
为此类规范创建数据访问的好方法是什么?有没有办法用ORM做到这一点?或者我是否需要编写特定于每个数据库的代码来支持这种情况?我是否有任何其他选项可以比直接使用ADO.NET更容易?
编辑:我认为我的问题写得过于宽泛,并没有明确解释,对此感到抱歉。问题是我不会创建数据库。它们将已经创建,并且程序应该能够通过在运行时配置程序来使用新数据库。我无法控制数据库。
另一件事是,当然可以通过在程序中创建SQL语句来实现,但这真的很麻烦。所有这些提供程序具有略微不同的规则和不同的SQL实现,因此它需要做很多工作。我想知道我是否可以使用像ORM这样的东西让我更容易。
编辑2:我完全清楚这是一种愚蠢的做事方式,它显示了糟糕的设计决策。但我花了这么多时间试图说服我的公司不这样做。他们不想改变他们的思维方式,因为实习生告诉他们。所以任何帮助都会受到赞赏。
答案 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
接口,所以它没有'无论你使用什么具体的课程(例如SqlConnection
或OracleConnection
),它都是一样的。
每个客户可能都有额外的列。
这实际上很直接。利用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
类,这些类只为正确的客户安装。现在,您拥有一系列针对系统的小型客户特定扩展,并且可以轻松开发,安装和维护这些扩展。