65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 ODBC 和 .NET 确保数据库可移植性

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.08/5 (12投票s)

2003年9月21日

6分钟阅读

viewsIcon

97402

downloadIcon

1168

管理您的源代码在不同 RDBMS 之间的可移植性,减少开发时间和维护。

引言

大多数时候(至少我),我们正在开发针对特定数据库服务器和平台的应用程序。但是,如果我们需要开发一个可能访问不同数据库引擎的解决方案会怎样?如果我们没有一个可以访问多个数据库的开发平台,我们将不得不为每个数据库引擎创建单独的代码,最终导致维护噩梦。通过 OOP 编程,访问多个数据库所需的代码变得更易于维护,但我们仍然需要为每个数据库编写特定的代码;您可以在 Pet Shop 3.0 blueprints 中看到一个示例。

ODBC,虽然不是一个神奇或完美的解决方案,但它允许我们使用通用代码访问多个数据库。在本文中,我将介绍使用 ODBC 时需要考虑的一些要点,以及一个旨在生成带有适当转义符的 SQL ODBC 语句的构建器类。要查找有关 ODBC 的更多信息,您可以访问以下链接

ODBC

ODBC 是一个附加层,它将带有 ODBC 转义符的通用 SQL 语句转换为特定的数据库 SQL 语法,从而允许使用通用代码访问多个数据库。访问不同数据库唯一需要做的就是指定另一个数据源。

需要注意的是,ODBC 不会取代数据库客户端软件。它只是翻译层,并且始终需要在访问数据库的计算机上安装数据库客户端软件。此外,我们连接的数据库需要一个驱动程序。实际上,大多数数据库都有一个 ODBC 驱动程序。

ODBC 的主要缺点之一是速度。这有几个原因

  • 它是一个额外的层,它抽象了 SQL 语法,并且必须将 SQL ODBC 语句转换为数据库特定的 SQL 语法。
  • 它也是一个通信桥梁。应用程序不直接与数据库客户端通信。所有数据都通过 ODBC 来回传递,这增加了一些额外的时间。
  • 可能存在一些数据类型转换。
  • 应用程序必须缩减到最小的通用规范,不能使用特定数据库引擎提供的强大功能和特性。例如,如果您的设计依赖于触发器,则不能将您的应用程序与 MS Access 一起使用。

另一个缺点是兼容性。如前所述,ODBC 是一个抽象层,需要数据库驱动程序。事实上,对于某些数据库,您可能会找到多个驱动程序。在一个驱动程序下工作良好的应用程序可能在另一个驱动程序下失败。此外,同一数据库的不同驱动程序之间可能存在性能差异。

ODBC 转义符

让我们将 ODBC 转义符视为一种新的 SQL 语法,它将由驱动程序转换为我们正在访问的数据库引擎的特定 SQL 语法。ODBC 转义符必须用“{}”括起来。

连接 “oj”

table_l: Table at the left
table_r: Table at the right
pk: Primary key
fk: Foreign key

LEFT OUTER JOIN

SELECT [fields list] FROM {oj table_l 
      LEFT OUTER JOIN table_r ON table_l.pk = table_r.fk }

INNER JOIN

对于 INNER JOINs,可以使用如下通用 SQL 语句

SELECT [fields list]  FROM table_l, table _r WHERE table _l.pk = table _r.fk

或使用 ODBC 转义符

SELECT [fields list] FROM {oj table_l INNER JOIN 
             table_r ON table_l.pk = table_r.fk }

日期、时间和时间戳 “d、t 和 ts”

WHEREINSERTUPDATE 子句需要以下转义符来引用 datetimetimestamps

Date: {d ‘yyyy-mm-dd’ }
Time: {t ‘hh:mm:ss’ }
Timestamp: {ts ‘yyyy-mm-dd hh:mm:ss’ }

函数 “fn”

“fn” 转义符允许执行标量函数。

示例

{fn UCASE(field) } LIKE ‘search string%’     // Starts with
{fn UCASE(field) } LIKE ‘%search string%’    // Contains

所有转义函数的参考可以在 此处 找到。

数据源名称和连接字符串

要使用 ODBC 连接到数据库,您可以使用数据源名称或动态连接字符串。

无论使用什么字符串,连接都以相同的方式打开

OdbcConnection con = new OdbcConnection(connectionString);
con.Open();

其中 connectionString 可以是其中之一。

数据源名称

数据源名称 (DSN) 必须使用 ODBC 面板创建。信息可以在 此处 找到。

连接字符串

动态连接字符串可以在运行时定义,而无需通过 ODBC 控制面板,这更加灵活和可配置。在提供的示例中,使用了动态连接字符串。

不同数据库服务器的连接字符串可以在 此处 找到。

设计数据库

在设计将通过 ODBC 与相同代码一起使用的数据库时,需要考虑几个要点。

  • 对于整数和小数,使用特定类型 (Integer, Double, Smallint) 而不是刻度和精度 (Numeric(x,y))。这将防止读取数据时出现转换异常。
  • 始终使用您目标的所有数据库测试您的应用程序。不要依赖一个数据库,然后打赌如果它在 SQL Server 上工作,它在 Oracle 或 DB2 上也会完美工作。
  • 记录 ODBC 和驱动程序版本;这有助于在部署应用程序时提供支持。同一数据库的不同驱动程序可能存在兼容性问题。
  • 开发一个标准的“ID 生成器”。所有数据库都提供不同的机制来获取唯一的 ID,ODBC 无法实现这一点。

安装 ODBC 提供程序

带有 1.0 框架的 Visual Studio .NET 不包括 ODBC 提供程序。提供程序可以从 此处 下载。

请记住将 Microsoft.Data.Odbc.dll 的引用添加到您的项目中。

代码

编写 SQL ODBC 语句可能单调且容易出错。.NET 框架提供了 SqlCommandBuilder 类,但只能用于使用参数创建 SQL 语句。要创建动态 SQL ODBC 语句,处理不同数据类型和转义符的类将非常有用。

使用方法

使用构建器类,可以创建 INSERTUPDATE SQL ODBC 语句。

实例化类

QueryBuilder qb = new QueryBuilder();

要创建 UPDATE,必须定义一个或多个键

qb.AddKey(field name, field value, FieldType);

键将用于构造 WHERE 子句。如果未定义键,则将创建 INSERT 子句。

构建器类可以处理 (FieldType)

  • String,将单引号替换为双引号。
  • 双精度浮点型.
  • 整数.
  • Boolean,将 true 转换为 1,将 false 转换为 0。
  • Date,使用 {d ‘yyyy-mm-dd’ } ODBC 转义符。
  • TimeStamp,使用 {ts ‘yyyy-mm-dd hh:mm:ss’ } ODBC 转义符。
  • Time,使用 {t ‘hh:mm:ss’} ODBC 转义符。

处理双精度浮点数、日期和时间的国际化。

获取 SQL ODBC 语句

// It will generate an INSERT or UPDATE depending on the keys
qb.ToString();  

INSERT 示例

QueryBuilder qb = new QueryBuilder();
qb.Table = "person";
qb.AddField("id", 1, FieldType.Integer);
qb.AddField("name", "My name's", FieldType.String);
qb.AddField("hireDate", System.DateTime.Now , FieldType.TimeStamp);
qb.AddField("active", true, FieldType.Boolean);
qb.AddField("salary", 1234.56, FieldType.Double);
textBox.Text = qb.ToString();

UPDATE 示例

QueryBuilder qb = new QueryBuilder();
qb.Table = "person";
qb.AddKey("id", 1, FieldType.Integer);
qb.AddField("name", "My name's", FieldType.String);
qb.AddField("hireDate", System.DateTime.Now , FieldType.TimeStamp);
qb.AddField("active", true, FieldType.Boolean);
qb.AddField("salary", 1234.56, FieldType.Double);
textBox.Text = qb.ToString();

结论

ODBC 在将应用程序移植到不同数据库方面非常强大和灵活,并且在处理 ODBC 转义符和国际格式的查询构建器的帮助下,为多个 RDBMS 进行开发所需的时间大大减少。

性能?是的,性能会付出代价,但如果您精确地定位应用程序,您会发现只有应用程序的一小部分可以使用特定的数据库代码进行改进。数据条目(插入、更新、读取和删除)可能最不容易通过特定代码进行优化,因此我们只需要专注于少数特定的业务流程并使用特定代码开发它们;也许,使用工厂,这样我们仍然可以将相同的应用程序与不同的 RDBMS 一起使用。

在拥有数百或数千并发用户的网站上,可伸缩性可能成为问题,您必须衡量使用 ODBC 的影响。

© . All rights reserved.