Multiple database support in C #

My application needs to support multiple databases. It currently supports Postgres, now I am adding support for Orcle and may be SqlServer in the coming days.

Before asking any questions, let's take a look at the codes.

IDbParser:

public interface IDbParser
{
    IDbConnection GetDbConnection(string ServerName, string DbPortNumber, string Username, string Password, string DatabaseName);
    IDbCommand GetDbCommand(string query, IDbConnection sqlConnection);
    IDataParameter CreateParameter(string key, object value);
    string GetDbQuery(DbQueries query);
}

      

OracleDbParser:

public class OracleParser : IDbParser
{
    #region >>> Queries
    private string SELECTGROUPSESSIONS = "....";
    ........
    #endregion

    public IDbCommand GetDbCommand(string query, IDbConnection sqlConnection)
    {
        var command = new OracleCommand();
        command.CommandText = query;
        command.Connection = (OracleConnection)sqlConnection;
        command.CommandType = CommandType.Text;
        command.CommandTimeout = 300;
        return command;
    }

    public IDataParameter CreateParameter(string key, object value)
    {
        return new OracleParameter(key, value);
    }        

    public IDbConnection GetDbConnection(string ServerName, string DbPortNumber, string Username, string Password, string DatabaseName)
    {
        connString = String.Format("Data Source=(DESCRIPTION = (ADDRESS_LIST = (ADDRESS=(PROTOCOL=TCP)(HOST={0})(PORT={1})))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME={2}))); Connection Timeout=60; User Id={3};Password={4};",
                                                ServerName, DbPortNumber, DatabaseName, Username, Password);
        return new OracleConnection(connString);
    }

    public string GetDbQuery(DbQueries query)
    {
        switch (query)
        {                
            case DbQueries.SELECTGROUPSESSIONS:
                return SELECTGROUPSESSIONS;
            ................
            ..............
            default:
                return String.Empty;
        }
    }
}

      

Likewise, there is a parser for Postgres:

public class PostgresParser : IDbParser
{
    #region >>> Queries
    private string SELECTGROUPSESSIONS = "....";
    ........
    #endregion

   public IDbCommand GetDbCommand(string query, IDbConnection sqlConnection)
    {
        var command = new NpgsqlCommand();
        command.CommandText = query;
        command.Connection = (NpgsqlConnection)sqlConnection;
        command.CommandType = CommandType.Text;
        return command;
    }

    public IDataParameter CreateParameter(string key, object value)
    {
        return new NpgsqlParameter(key, value);
    }       

    public IDbConnection GetDbConnection(string ServerName, string DbPortNumber, string Username, string Password, string DatabaseName)
    {
        string connString = String.Format("Server={0};Port={1};Timeout=60;CommandTimeout=300;" +
                                            "User Id={2};Password={3};Database={4};",
                                            ServerName, DbPortNumber, Username, Password, DatabaseName);
        return new NpgsqlConnection(connString);
    }


    public string GetDbQuery(DbQueries query)
    {
        switch (query)
        {                
            case DbQueries.SELECTGROUPSESSIONS:
                return SELECTGROUPSESSIONS;
            ................
            ..............
            default:
                return String.Empty;
        }
    }
}

      

DatabaseParserFactory:

 public class DatabaseParserFactory
{
    public static IDbParser GetDbParser(string dbType)
    {
        CUCMDbType dbTypeName;
        Enum.TryParse(dbType.ToLower(), out dbTypeName);
        switch (dbTypeName)
        {
            case CUCMDbType.oracle:
                return new OracleParser();
            case CUCMDbType.postgres:
                return new PostgresParser();
            default:
                return new PostgresParser();
        }
    }
}

      

Executing the request:

 public void Query(string queryStatement, DbParameterColl parameters, Action<IDataReader> processReader)
    {
        using (SqlConnection)
        {
            IDbCommand selectCommand = null;                
            selectCommand = _factory.GetDbCommand(queryStatement, SqlConnection);                     
            selectCommand.Parameters.Clear();

            using (selectCommand)
            {
                if (parameters != null)
                {
                    foreach (var param in parameters)
                    {
                        selectCommand.Parameters.Add(_factory.CreateParameter(param.Key, param.Value));                           
                    }
                }

                try
                {                 
                    using (var reader = selectCommand.ExecuteReader())
                    {
                        processReader(reader);
                    }

                }
                catch (Exception ex)
                {
                    Logger.DebugFormat("Unable to execute the query. Query : {0} . Exception: {1}", queryStatement, ex);
                    Debug.WriteLine("\n\n>> Error on executing reader. Exception :\n " + ex);
                }
            }
        }
    }

      

FYI: There will only be SELECT queries and other commands.

I am passing the parameter value as an object. Well, there is currently no problem with parameter assignment and query execution. But in most blogs and on stackoverflow, I've seen people suggest input direction, most specifically Input Type / DbType . Do I need to specify DbType? Currently my code is working fine with no errors. But I'm afraid it might break in production.

Also, I have no control over the type of the parameter, it could be anything. So what do you suggest? Or is there a better way to do this?

+3


source to share


1 answer


First, you should take a look at DbProviderFactories - most of your code duplicates existing standard functionality. Please note that it is not yet available in .NET Core (but will be).



As for your question, in general you don't need to specify the direction of the parmeter - it is considered the default. Database drivers can usually infer the database type from the CLR value you assign to the parameter, but it's a good idea to explicitly specify the DbType to be sure.

+1


source







All Articles