Дублирование кода, одинаковая функциональность, разные типы

У меня есть этот метод, который работает с Npgsql:

private DataTable GetTableN(string sql, string[] pars)
    {
        NpgsqlCommand zapytanie = new NpgsqlCommand(sql, connn, trann);
        NpgsqlDataAdapter da = new NpgsqlDataAdapter();
        DataSet ds = new DataSet();
        try
        {
            if (pars != null)
            {
                for (int i = 0; i < pars.Length; i++)
                {
                    zapytanie.Parameters.AddWithValue("@param" + i, pars[i]);
                }
            }
            connn.Open();
            da.SelectCommand = zapytanie;
            da.Fill(ds);
            return ds.Tables[0];
        }
        catch (NpgsqlException e)
        {
            throw (new SqlException(e.Message.ToString()));
        }
        finally
        {
            connn.Close();
            zapytanie.Dispose();
            da.Dispose();
            ds.Dispose();
        }
    }

теперь мне нужен точно такой же метод, но с использованием Odbc. Мне нужно только внести эти изменения

  1. NpgsqlCommand в ObdcCommand
  2. NpgsqlDataAdapter в OdbcDataAdapter
  3. NpgsqlException для OdbcException

Как мне объединить это, чтобы избежать дублирования кода и иметь только один метод?


person jankes    schedule 03.08.2016    source источник
comment
Иметь логическое значение, использовать ODBC или что-то в этом роде и соответственно кодировать?   -  person BugFinder    schedule 03.08.2016
comment
Хорошо, и как мне избежать дублирования блоков try finally?   -  person jankes    schedule 03.08.2016
comment
Хотя я не использовал команды NGpgsql, они не выглядят по-другому, поэтому единственным очевидным изменением будет захват odbceexception.. так что просто добавьте еще один улов..   -  person BugFinder    schedule 03.08.2016
comment
вы не можете предотвратить дублирование кода после точки. Что делать, если вам нужно использовать другую базу данных в будущем? больше кода, чтобы предотвратить дублирование кода. сделать заводской шаблон для такого рода ситуаций. это самый чистый способ.   -  person Doruk    schedule 03.08.2016


Ответы (2)


вы можете попробовать изменить подпись вашего метода

private DataTable GetTableN(string sql, string[] pars, DbCommand zapytanie, DbDataAdapter da)
{   
    DataSet ds = new DataSet();
    try
    {
        if (pars != null)
        {
            for (int i = 0; i < pars.Length; i++)
            {
                zapytanie.Parameters.AddWithValue("@param" + i, pars[i]);
            }
        }
        connn.Open();
        da.SelectCommand = zapytanie;
        da.Fill(ds);
        return ds.Tables[0];
    }
    catch (DbException e)
    {
        throw (new SqlException(e.Message.ToString()));
    }
    finally
    {
        connn.Close();
        zapytanie.Dispose();
        da.Dispose();
        ds.Dispose();
    }
}

или использовать какую-то фабрику

private DataTable GetTableN(string sql, string[] pars, MyFactory factory)
{
    DbCommand zapytanie = factory.CreateCommand(...);
    DbDataAdapter da = new factory.CreateAdapter(...);
    ...
}

или вы можете использовать наследование для этого

public abstract class MyClass
{
    private DataTable GetTableN(string sql, string[] pars)
    {
        DbCommand zapytanie = CreateCommand();
        DbDataAdapter da = CreateAdapter();
        ...
    }

    protected abstract DbCommand CreateCommand();
    protected abstract DbDataAdapter CreateAdapter();
}

public class OdbcClass : MyClass
{
    protected override DbCommand CreateCommand()
    {
        // create for odbc
    }

    protected override DbDataAdapter CreateAdapter()
    {
        // create for odbc
    }
}

public class PostgrClass : MyClass
{
    protected override DbCommand CreateCommand()
    {
        // create for postgr
    }

    protected override DbDataAdapter CreateAdapter()
    {
        // create for postgr
    }
}
person tym32167    schedule 03.08.2016

Я думаю, что фабричная модель - это то, что нужно. Спасибо.

person jankes    schedule 03.08.2016