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

使用 ADO.NET 将项目连接到任何数据库的便捷代码

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.78/5 (10投票s)

2009 年 7 月 2 日

CPOL

5分钟阅读

viewsIcon

50559

downloadIcon

354

纯粹的面向对象的 ADO 代码组件,无论您后端使用什么数据库,都能让您的项目运行起来。专为 SQL Server 设计。

引言

这是完全重写的第一篇文章。我感谢所有为改进文章提供宝贵建议的人。感谢大家。我在 ADO.NET 应用程序开发过程中发现,开发人员在泛化他们的数据库实用类以便它们能够与后端提供的任何数据库配合使用时并不轻松。这在您实现 SOA 时非常有用。因此,我们将创建一个通用的类集,您可以使用它们来使您的代码在 ADO.NET 支持的任何给定数据库上运行。

背景

此实用程序使用了基本 OOP 的概念,如动态方法分派 (DMD)、运算符重载、继承、结构体、枚举等,还包括自定义异常和集合的概念。此实用程序背后的核心概念是使用 System.Data.Common 中的核心数据库类,我已对其进行操作和继承以使功能性类能够运行。

Using the Code

虽然理解此代码有点复杂,但使用它非常简单(只需两行代码)。我已在 SQL Server、Access、Excel、Oracle、XML 以及可通过 OLE DB 连接的一些数据库上测试了此代码。

代码包含一个名为 DataAccess 的治理器类,它有助于封装数据访问逻辑。除了 XML 之外,每种受支持的数据库都有一个对应的类,例如 SQLFactoryProviderAgnosticFactory,它们实现了相同的功能。由于要实现的功能相同,因此我将所有通用方法都放在它们的基类 FactoryGoverner 中,该类指定了由其派生类重写的虚拟函数。我们称 Factory Governer 类为治理器。治理器类使用 DMD 来动态调用相应派生类中的相应方法。此类是为了与 ASP.NET 一起使用而创建的,但通过在 DataAccess 中添加另一个构造函数,使其适用于 Windows 应用程序,例如:

public DataAccess(string conStr, string providerName)
{
    connectionString = conStr;
    provider = providerName;
}

您可以像我为 SQL Server (SQLFactory) 添加那样,向该实用程序添加更多此类专用类。专用类的性能远优于通用类 (ProviderAgnosticFactory)。请注意,由于我使用了 DMD,因此在添加专用类时,您需要实现 FactoryGoverner 中指定的相同方法。另一点值得注意的是,对于 ASP.NET,您需要使用包装类 DataAccess 的另一个构造函数,您需要在其中提供在 web.config 中为连接字符串指定的配置名称。

public DataAccess(string configSectionName) 
{ 
    connectionString = 
        WebConfigurationManager.ConnectionStrings[configSectionName].ToString(); 
    try 
    { 
        provider = DbProviderFactories.GetFactory(
            WebConfigurationManager.ConnectionStrings[configSectionName].ProviderName); 
    } 
    catch (DbException ex) 
    { 
    } 
}

请注意,该实用程序通过查看提供程序来区分要调用的函数,因此请始终使用标准的提供程序名称,例如:System.Data.SqlClientSystem.Data.OracleClientSystem.Data.OleDbSystem.Data.Odbc。如果未使用这些提供程序中的任何一个,则会抛出自定义异常 UnsupportedFactoryException,它使用 Exception 的派生类。

[Serializable]
public class _Exception : Exception
{
    public string ErrorMessage
    {
        get
        {
            return base.Message.ToString();
        }
    }

    public _Exception(string errorMessage)
        : base(errorMessage)
    {
    }

    public _Exception(string errorMessage, Exception innerEx)
        : base(errorMessage, innerEx)
    {
    }
}

其他结构和枚举不言自明。但我会强调一个对于简化事情非常重要的特定结构。AgnosticParameter 是用于承载您的查询或存储过程参数的结构。您可以根据需要向查询或存储过程提供任意数量的参数。参数可以按顺序提供,也可以作为 AgnosticParameters 数组提供。

public struct AgnosticParameter
{
    #region Public Member Variables
    public string ParameterName;
    public object ParameterValue;
    #endregion

    #region Constructors
    // Parameterized Constructor
    public AgnosticParameter(string ParameterName, 
                             object ParameterValue)
    {
        this.ParameterName = ParameterName;
        this.ParameterValue = ParameterValue;
    }

    // Copy Constructor
    public AgnosticParameter(AgnosticParameter sourceParameter)
    {
        this.ParameterName = sourceParameter.ParameterName;
        this.ParameterValue = sourceParameter.ParameterValue;
    }
    #endregion

    #region Overloaded Operators
    public static bool operator ==(AgnosticParameter lValue, AgnosticParameter rValue)
    {
	    return (lValue.ParameterName.Equals(rValue.ParameterName) 
	    	&& lValue.ParameterValue.Equals(rValue.ParameterValue));
    }	

    public static bool operator !=(AgnosticParameter lValue, 
				AgnosticParameter rValue)
    {
        return (lValue.ParameterName != rValue.ParameterName || 
		lValue.ParameterValue != rValue.ParameterValue);
    }

    public override bool Equals(object obj)
    {
        return base.Equals(obj);
    }

    public override int GetHashCode()
    {
        return base.GetHashCode();
    }
    public override string ToString()
    {
        return base.ToString();
    }
    #endregion
}

重载的运算符将帮助您比较此结构的两对象。

现在让我们分析 CustomConnection 类及其用法。首先,创建此类的灵感来自于 **Paulo** 先生提供的评论。Custom Connection 类用于实例化 DbProviderFactory 对象,并将其与已知的数据库提供程序进行比较,以了解涉及的数据库。这也有助于我们实例化 DbProviderFactory 来处理我们的自定义 XML 工厂。我们很快就会看到如何实现。让我们先分析代码。

public class CustomConnection : DbProviderFactory
{
    private enum SetCustomFactory
    {
        Xml_Factory = 0
    }

    SetCustomFactory selectedFactory;

    public CustomConnection()
    {
        //No Constructor Logic Needed.
    }

    public CustomConnection(bool isXmlSource)
        : base()
    {
        //To Instantiate DbProviderFactory
        selectedFactory = SetCustomFactory.Xml_Factory;
    }

    public FactoryCodes TypeOfConnection(DbProviderFactory provider)
    {
        if (provider is System.Data.SqlClient.SqlClientFactory)
            return FactoryCodes.SQLClient;
        else if (provider is System.Data.OracleClient.OracleClientFactory)
            return FactoryCodes.OracleClient;
        else if (provider is System.Data.Odbc.OdbcFactory)
            return FactoryCodes.ODBC;
        else if (provider is System.Data.OleDb.OleDbFactory)
            return FactoryCodes.OleDB;
        //For Future Enhacements Both Clauses Return XML
        else if (provider is CustomConnection)
            return (selectedFactory == 
                SetCustomFactory.Xml_Factory) ? FactoryCodes.XML : FactoryCodes.XML;
        throw new UnsupportedFactoryException("Database Is Unsupported");
    }
}

您会看到此类有一个方法可以比较提供程序类型并帮助调用相关工厂类中的适当方法。现在,您只需使用另外一行代码即可实例化一个 DbProviderFactory 对象以与 XML 一起使用,而这在此之前仅通过使用 DbProviderFactories 才有可能实现。

DbProviderFactory xmlProvider = new CustomConnection(true);

请注意,只有在使用 XML 数据源时才需要执行此类实例化。编写此行后,您将按照与其他任何数据库相同的过程进行操作。 现在,进入非 XML(以及在使用上述代码后对 XML)的可用性部分。将所有这些类添加到项目中后,查询任何数据库只需提供一个配置并传递查询即可。例如,假设您有两个配置:

<connectionStrings>
    <add name="TestPool" 
     connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=
                       |DataDirectory|\TestPool.mdf;Integrated Security=True;
                       User Instance=True"
     providerName="System.Data.SqlClient" />

    <add name="OleDB"
     connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=
                       |DataDirectory|\AccessFile.accdb;
                       Persist Security Info=True"
     providerName="System.Data.OleDb" />
</connectionStrings>

如果您想查询数据库,则可以通过提供查询或存储过程(视情况而定)来执行此操作,例如(我为各种可能性编写了虚拟代码,选择其中任何一个):

 DbProviderFactory objDF = new CustomConnection(true);
 DataAccess objD1 = new DataAccess("Path To XML", objDF);
 //OR
 DataAccess objD2 = new DataAccess("Web Config Section Name");
 // OR
 DataAccess objD3 = new DataAccess("Connection String",
     DbProviderFactories.GetFactory("System.Data.SqlClient"));

然后是您想要的任何查询结果,例如:

DataSet d = new DataSet();
d = objD2.GetDataSet(QueryType.Text, "SELECT * FROM Table1");

请记住,如果您尝试在任何地方使用不可实现的函数,您将收到 UnsupportedFactoryException,例如在使用 SQL Server 作为提供程序时使用 CreateXMLDocument。

非常简单。

关注点

我曾经花了两天时间思考为什么 Excel 无法与我的代码一起工作,然后我学到了一件事。使用正确的连接字符串!!

如果您喜欢此实用程序,我别无所求,只希望得到赞赏。请告诉我如何帮助您。这是我的第一篇文章,请不要介意我生硬的解释。

可能的补充

您可以随时向代码中添加专门的工厂类。

历史

  • 2009 年 7 月 2 日:初始发布
  • 2009 年 7 月 7 日:文章修改,更新源代码
  • 2009 年 7 月 10 日:文章修改,更新源代码
© . All rights reserved.