【问题标题】:C# - A class for Generic database connection, command, readerC# - 通用数据库连接、命令、阅读器的类
【发布时间】:2009-07-10 05:15:55
【问题描述】:

假设我正在设计一个可以处理任何数据库技术以创建连接、执行命令和检索数据等的类。

如果我需要为现有的 RDBMS(如 SQL Server、Oracle、FireBird 等)创建一个通用数据库处理类,我应该使用哪个 .net 抽象类/接口 {DbConnection, DbCommand, DbParameter,... } 或 {IDbConnection, IDbCommand, IDbParameter,...}?

我应该使用类似的代码

public bool CreateConnection(DatabaseTypeEnum type)
{
    DbConnection conn ;

    if(type==DatabaseTye.Oracle)
    {
        //....
    }    
}

public DbDataReader GetData()
{

    DbCommand comm;
    //...
}

或者,

public bool CreateConnection(DatabaseTypeEnum type)
{
    IDbConnection conn ;

    if(type==DatabaseTye.Oracle)
    {
        //....
    } 
}

public IDbDataReader GetData()
{

    IDbCommand comm;
    //...
}

那么,为什么?

【问题讨论】:

  • 你的意思是问:我什么时候需要创建一个通用的......?为什么?
  • 请查看更新后的问题。
  • 建议使用接口而不是确切的实现来编程。因此,在您的代码中,首选第二个选项。类似的讨论已经在 Stack Overflow 中讨论过:stackoverflow.com/questions/383947/…stackoverflow.com/questions/570302/when-are-interfaces-needed
  • 在谈论 C# 时要小心使用“通用”这个词,因为它具有与这个问题无关的非常具体的含义。

标签: c# ado.net


【解决方案1】:

Ermm...完全不同的问题:)

好吧,也没有……

当你这样做时,你将违反打开关闭原则......那个特定位置的 switch / if 语句让我感到不舒服:)。

我会将实际创建留给 Factory 类,您的代码不应该关心它是在与 SQL Server、DB2 还是 Oracle 或其他什么对话。

理想情况下,您的代码应该只与 IDbConnection、IDbCommand 等或抽象基类(DbConnection、DbCommand 等)对话。有时我确实发现您需要向上转换到特定的提供程序(例如使用特定方法的 SqlDataReader),但这种情况很少见。

Factory 会将这个 switch / if 语句封装到一个地方,以便于维护。您可以在 app.config 中进一步抽象实际创建。因此,在 app.config 中,您可以选择所支持的数据库后端类型,Factory 将从那里获取并为您创建必要的数据库内容。

请参阅:this。阅读有关创建 DbProviderFactory 和连接部分的信息...

【讨论】:

  • +1 来自我。在工厂中,我使用连接字符串中的 providerName 映射到 providerSettings 以获取特定于提供者的内容,例如参数前缀(例如,“@”代表 MSSQL,“:”代表 Oracle 等)。
【解决方案2】:

为什么不使用泛型?

你可以像这样定义你的类,例如:

public class DBHelper<T, Y, W> where T: DbConnection, new() where Y : DbCommand, new()
{
        private T conn_ = new T();
        private Y comm_ = new Y();            
}

这就是我要做的,而且它真的很容易维护。

【讨论】:

  • 这里不需要 Y 类型参数,因为 DbCommand 可以从连接对象实例化,例如 conn.CreateCommand()。还有什么是 W 类型参数?
【解决方案3】:

您应该使用IDbConnectionIDbCommand,因为不同的数据库供应商将有不同的接口实现(对于他们的ADO.NET 事物),但更好 与您发布的不完全一样。您应该改为使整个类通用以支持通用IDbConnectionIDbCommand。可能是这样的:

public class Db<T> where T : IDbConnection, new()
{
    public bool CreateConnection()
    {
        T conn;

        //now you dont need these lines since you dont have to worry about
        //what type of db you are using here, since they all implement
        //IDbConnection, and in your case its just T.
        //if(type==DatabaseTye.Oracle)
        //{
            //....
        //}
    }

    public DbDataReader GetData()
    {
        //get comm object from S conn
        using(var conn = new S())
            using (var comm = conn.CreateCommand())

        //...
    }

好处是你可以将你想要用于DbConnectionDbCommand 的类型传递给这个类,这对于MySQL .net 连接器和Oracle 来说是不同的。因此,您可以从课堂外获得某种控制。您可以查看question and my answer 以获取基本实现的参考。

【讨论】:

    猜你喜欢
    • 2018-04-12
    • 1970-01-01
    • 1970-01-01
    • 2017-01-09
    • 1970-01-01
    • 2019-11-27
    • 1970-01-01
    • 2014-08-05
    • 1970-01-01
    相关资源
    最近更新 更多