-1

我有两个要使用泛型组合的功能。

    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;
    }

但我得到了上面显示的错误。

如果我将容器更改为动态它会编译。但这似乎是一个黑客行为。结合这两个功能的正确方法是什么?

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

因为DataSetandDataTable是完全独立的类,并且您必须为SqlDataAdapter.Fill它们中的每一个使用不同的重载,您将无法使用泛型方法将您的两个方法简化为一个。但是,您可以使用一个方法来减少重复代码,该方法接受一个委托,该委托定义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 回答