保持应用程序数据库不可知(ADO.NET与封装DB逻辑)

我们正在制作一个相当严肃的应用程序,需要与客户想要使用的数据库保持不可知。 最初我们计划支持MySQL,Oracle和SQL Server。 表和视图很简单,查询(没有真正奇特的SQL),因此问题:

  1. 使用本机数据库驱动程序(MySQLDbConnection等)并封装执行查询和处理结果的逻辑或
  2. 使用通用的OleDbConnection

显然,选项2不涉及开销,但我认为性能不如原生访问那么好?

注意:如果您决定使用基本的ADO.NET 2function而不是ORM(例如Entity Framework或NHibernate)或LINQ to SQL,则此答案是相关的。

假设您在app.config定义了一个连接字符串:

    

请注意providerName属性及其值的存在。 您还可以为另一个数据库提供程序输入值,例如System.Data.SQLite

(请注意,非标准提供程序,即默认情况下不在.NET Framework中的提供程序, 需要先在app.config或客户端计算机的machine.config 。)

现在,您可以使用完全与提供程序无关的方式使用指定的数据库,如下所示:

 using System.Configuration; // for ConfigurationManager using System.Data; // for all interface types using System.Data.Common; // for DbProviderFactories var cs = ConfigurationManager.ConnectionStrings["SomeConnection"]; // ^^^^^^^^^^^^^^^^ var factory = DbProviderFactories.GetFactory(cs.ProviderName); // ^^^^^^^^^^^^^^^ using (IDbConnection connection = factory.CreateConnection()) { connection.ConnectionString = cs.ConnectionString; // ^^^^^^^^^^^^^^^^^^^ connection.Open(); try { using (IDbCommand command = connection.CreateCommand()) { ... // do something with the database } } finally { connection.Close(); } } 

请注意此代码仅适用于接口类型。 您指定特定数据库提供程序的唯一位置是通过app.config文件中的providerName属性值。 (我已经用^^^ s标记了app.config设置的所有地方。)


进一步阅读:

  • 使用ADO.NET 2.0基类和工厂进行通用编码 :
    类似于我的回答,但更详细。

  • ADO.NET托管提供程序和DataSet开发人员中心 :
    除其他外,还包括可用ADO.NET数据库提供程序的索引。

使用ORM的 IMHO是一个很好的设计决策,以便拥有一个与数据库无关的应用程序。 切换数据库可能就像更改配置设置和连接字符串一样简单。

您不需要OleDbConnection来访问非特定的ADO.NET提供程序。 只需使用DbConnection等。 人。 有关详细信息,请参阅MSDN上的DbProviderFactories

通过在该列表中包含Oracle,您可以保证一切都不会那么简单。

  • 与使用“at”符号的SQL Server相比,Oracle对参数使用不同的前缀字符(冒号)。
  • Oracle对long,int,short,boolean,float和decimal使用单个数据类型(数字); 您的代码必须确保您正确映射这些代码。
  • 您必须参数化Oracle日期和时间值; 如果您尝试在SQL语句中使用字符串作为日期,那么由于Oracle的日期格式,您将会疯狂。 (Oracle使用三个字符的月份缩写;格式为01-JAN-2010。)
  • 用于处理空值的基本SQL函数可能不同,尤其是对于空合并。 (“NVL”与“COALESCE”)Oracle对于保留字更加挑剔。
  • Oracle没有本机标识列支持。 变通办法涉及序列,触发器和要求事务只是为了从新行检索标识值。

换句话说,您的应用程序不能与数据库无关。 如果您不使用ORM,您肯定希望构建一个数据访问层,从应用程序的其余部分隐藏所有这些内容。

这里有经验之谈。 只是在说’。 对于跨SQL Server和Oracle的通用模式,我们必须构建ORM的大部分基础结构,同时避免可能降低性能的方面。 肯定有趣但非平凡!

LINQ是备受推崇的.NET ORM,部分原因是您可以使用它和存储过程。 问题是,它只是SQL Server,但人们正致力于为Oracle和MySQL提供类似的function。

对于数据库和查询优化,我对使用ORM的想法感到畏缩。 SQL中的数据类型,函数和整体语法不是很容易移植。 与每个数据库交互的最高效的方法是为每个数据库定制模型和查询,但这意味着专业知识,时间和金钱。 如果需要,请关注一个具有代码设置的数据库供应商,以支持供应商交换,并根据需要添加对其他数据库的支持。

没有充分的理由避免使用最广泛支持的最通用的接口 – OleDb甚至是ODBC,如果你对它们感到满意的话。 除此之外的任何东西都会减少您可以使用的产品/语言/平台/工具/开发人员库。 由于最接近SQL金属,供应商不会引入太多低效率 – 肯定比更深奥的选择更少。 他们已经花了很长时间来解决任何问题。

如果你要添加一个抽象层(你自己或别人的),那么这应该根据你特定上下文中引入的抽象的优点来决定,而不仅仅是有一个抽象层(这只是更多的支持,除非这是有意的好处。)

如您所见,每个人的里程各不相同。 :)但总的来说,我认为更简单更好。

为什么不使用Microsoft 模式和实践 企业库数据访问应用程序块。 最小的开销和交换提供商非常容易。

引用:

数据访问应用程序块利用这些类并提供进一步支持封装数据库类型特定function的模型,例如参数发现和类型转换。 因此,可以将应用程序从一种数据库类型移植到另一种数据库类型,而无需修改客户端代码。

通过让大量应用程序将DAL用作一堆接口,您始终可以使应用程序数据库的一部分不可知。 然后,DAL本身将为目标数据库提供具体实现。

这样,您就可以在DAL的使用中脱钩,但是DAL中的性能改进或供应商特定构造的好处。