用于数据库访问的抽象层

本文关键字:抽象 访问 数据库 用于 | 更新日期: 2023-09-27 18:02:11

我想为mysql和mssql编写自定义SQL代码(可能稍后)。

var dbSystem = "mssql";
if ("mssql" == dbSystem) {
    var mssqlConn = new SqlConnection(mssqlConnString);
    new SqlCommand("CREATE TABLE t1 (c1 in NOT NULL PRIMARY KEY IDENTITY(1,1), c2 int)", mssqlConn).ExecuteNonQuery();
} else {
    var mysqlConn = new MySqlConnection(mysqlConnString);
    new SqlCommand("CREATE TABLE t1 (c1 in NOT NULL AUTO_INCREMENT PRIMARY KEY, c2 int)", mssqlConn).ExecuteNonQuery();
}

问题从这里开始。我希望在if语句之前通过接口或抽象类声明连接。但这似乎是不可能的,因为命令类明确要求特定的SqlConnection或MySqlConnection。

如果您想执行像SELECT c1 form t1 where c2 = @value这样的简单命令,问题会变得更糟。因为你必须做同样的事情。

是否有这样的API服务于工作流:

IDbConnection conn; // initialized by SqlConnection or MySqlConnection, etc.
IDbCommand cmd = new DbCommand("SELECT c1 form t1 where c2 = @value", conn);
cmd.Parameters.Add("@value", Type.Int);

问题:

  • System.Data.Common。DbCommand是一个抽象类
  • SqlDbCommand (MySqlDbCommand等)要求有特定的连接
  • DbCommand。属性不支持"添加"与两个参数("@placeholer",值)像SqlDbCommand的属性
  • 我不需要/想要一个完整的ORM;只是在现有异构API之上的一个接口/抽象层

用于数据库访问的抽象层

方法是使用DbProviderFactories.GetFactory(String)来检索DbProviderFactory对象。

使用DbProviderFactory.CreateConnection()会给你一个DbConnection对象。

设置此DbConnection对象的ConnectionString属性并调用Open()方法将导致打开到所需数据库的连接。

使用DbConnection.CreateCommand()将给你一个DbCommand对象,你可以随心所欲地使用。

对于使用参数化查询,您可以使用DbCommand.CreateParameter(),它将返回一个DbParameter对象。

:

// MySQL
DbProviderFactory factory = DbProviderFactories.GetFactory("MySql.Data.MySqlClient"); 
// MS-SQL
DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.SqlClient");  
private void Query(String query,Dictionary<String,object> namesAndValues, System.Data.CommandType commandType)
{
    String connectionString = ConfigurationManager.ConnectionStrings["yourConnectionString"];
    using (DbConnection connection = factory.CreateConnection())
    {
        connection.ConnectionString = connectionString;
        connection.Open();
        using (DbCommand command = connection.CreateCommand())
        {
            command.CommandText = query;
            command.CommandType = commandType;
            AddParameters(command, namesAndValues);
            using (DbDataReader reader=command.ExecuteReader())
            {
                while (reader.Read())
                {
                 //
                }
            }
         }
    }
}
private void AddParameters(DbCommand command, Dictionary<String, object> namesAndValues)
{
    String factoryName = factory.GetType().Name;
    DbParameter para;
    foreach (String key in namesAndValues.Keys)
    {
        para = command.CreateParameter();
        switch (factoryName)
        {
            case "SqlClientFactory":
                para.ParameterName = "@" + key;
                break;
             case "OracleClientFactory":
                para.ParameterName = ":" + key;
                break;
            case "OleDbFactory":
                para.ParameterName = "?";
                break;
            case "MySqlClientFactory":
                para.ParameterName = "?" + key;
                break;
        }
        para.Value = namesAndValues[key];
        command.Parameters.Add(para);
    }
}

您总是可以使用抽象出具体驱动实现的DbProviderFactory。http://msdn.microsoft.com/de-de/library/system.data.common.dbproviderfactory (v = vs.110) . aspx

对于数据库特定的SQL命令,您还需要创建某种抽象。像

interface IQueryBuilder{
  string BuildCreateTableQuery();
}
class MySqlQueryBuilder : IQueryBuilder {
}
class SqlQueryBuilder : IQueryBuilder {
}
class OracleQueryBulder : IQueryBuilder{
}