-1

ジェネリックを使用して結合したい 2 つの関数があります。

    static public DataTable GetDataTable(SqlParameterHash parameters, string sql,
        string connectionString, CommandType commandType = CommandType.StoredProcedure)
    {
        var da = new SqlDataAdapter(sql, connectionString);
        da.SelectCommand.CommandType = commandType;
        da.SelectCommand.CommandTimeout = 0;

        foreach (SqlParameter Parameter in parameters)
        { da.SelectCommand.Parameters.Add(Parameter); }

        DataTable dt = new DataTable();
        da.Fill(dt);
        return dt;
    }

    static public DataSet GetDataSet(SqlParameterHash parameters, string sql,
        string connectionString, CommandType commandType = CommandType.StoredProcedure)
    {
        var da = new SqlDataAdapter(sql, connectionString);
        da.SelectCommand.CommandType = commandType;
        da.SelectCommand.CommandTimeout = 0;

        foreach (SqlParameter Parameter in parameters)
        { da.SelectCommand.Parameters.Add(Parameter); }

        DataSet ds = new DataSet();
        da.Fill(ds);
        return ds;
    }

これは私が思いついたものです:

    static private T GetDataX<T>(T container
        , SqlParameterHash parameters, string sql, string connectionString
        , CommandType commandType = CommandType.StoredProcedure
        ) where T : System.ComponentModel.MarshalByValueComponent, new()
    {
        var da = new SqlDataAdapter(sql, connectionString);
        da.SelectCommand.CommandType = commandType;
        da.SelectCommand.CommandTimeout = 0;

        foreach (SqlParameter Parameter in parameters)
        { da.SelectCommand.Parameters.Add(Parameter); }

        da.Fill(container); // ERROR: cannot convert from 'T' to 'System.Data.DataTable'
        return container;
    }

しかし、上記のエラーが表示されます。

コンテナーを動的に変更すると、コンパイルされます。しかし、それはハックのようです。2 つの機能を組み合わせる適切な方法は何ですか?

4

2 に答える 2

3

Actionサポートするタイプごとに塗りつぶしを行うパラメーターを追加できます。

static private T GetDataX<T>(SqlParameterHash parameters, string sql, string connectionString, Action<T, SqlDataAdapter> fillAction, CommandType commandType = CommandType.StoredProcedure) 
    where T : System.ComponentModel.MarshalByValueComponent, new()
{
    SqlConnection connection = new SqlConnection(connectionString);
    connection.Open();

    SqlDataAdapter da = new SqlDataAdapter(sql, connection);
    da.SelectCommand.CommandType = commandType;
    da.SelectCommand.CommandTimeout = 0;

    foreach (SqlParameter Parameter in parameters)
    { da.SelectCommand.Parameters.Add(Parameter); }

    T container = new T();
    fillAction(container, da);
    da.SelectCommand.Parameters.Clear();
    return container;
}

次に、これに関して他のメソッドを記述できます。

static public DataTable GetDataTable(SqlParameterHash parameters, string sql,
        string connectionString, CommandType commandType = CommandType.StoredProcedure)
{
    return GetDataX<DataTable>(parameters, sql, connectionString, (dt, adapter) => { adapter.Fill(dt); }, commandType);
}

static public DataSet GetDataSet(SqlParameterHash parameters, string sql,
        string connectionString, CommandType commandType = CommandType.StoredProcedure)
{
    return GetDataX<DataSet>(parameters, sql, connectionString, (ds, adapter) => { adapter.Fill(ds); }, commandType);
}
于 2012-10-11T20:38:31.967 に答える
1

DataSetDataTableは完全に別個のクラスであり、それぞれに異なるオーバーロードを使用する必要があるためSqlDataAdapter.Fill、ジェネリックメソッドを使用して2つのメソッドを1つに単純化することはできません。ただし、メソッドの実行中に何を処理するかを定義するデリゲートを使用するメソッドを使用して、繰り返しコードを減らすことができますSqlDataAdapter

public static DataTable GetDataSet(
    SqlParameterHash parameters, string sql, string connectionString,
    CommandType commandType = CommandType.StoredProcedure
)
{
    DataSet ds = new DataSet();
    UseDataAdapter(
       parameters, sql, connectionString,
       da => da.Fill(ds), commandType
    );
    return ds;
}

public static DataTable GetDataTable(
    SqlParameterHash parameters, string sql, string connectionString,
    CommandType commandType = CommandType.StoredProcedure
)
{
    DataTable dt = new DataTable();
    UseDataAdapter(
       parameters, sql, connectionString,
       da => da.Fill(dt), commandType
    );
    return dt;
}

public static void UseDataAdapter(
    SqlParameterHash parameters, string sql, string connectionString,
    Action<SqlDataAdapter> adapterAction,
    CommandType commandType = CommandType.StoredProcedure
)
{
    SqlConnection connection = new SqlConnection(connectionString);
    connection.Open();

    SqlDataAdapter da = new SqlDataAdapter(sql, connection);
    da.SelectCommand.CommandType = commandType;
    da.SelectCommand.CommandTimeout = 0;

    foreach (SqlParameter Parameter in parameters)
    { da.SelectCommand.Parameters.Add(Parameter); }

    adapterAction(da);

    da.SelectCommand.Parameters.Clear();
    return dt;
}
于 2012-10-11T20:36:39.317 に答える