C# 如何使用干式主体重构此代码?
我想使用泛型组合两个函数C# 如何使用干式主体重构此代码?,c#,generics,dry,C#,Generics,Dry,我想使用泛型组合两个函数 static public DataTable GetDataTable(SqlParameterHash parameters, string sql, string connectionString, CommandType commandType = CommandType.StoredProcedure) { var da = new SqlDataAdapter(sql, connectionString);
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;
}
static private T GetDataX(T容器
,SqlParameterHash参数,字符串sql,字符串连接字符串
,CommandType CommandType=CommandType.StoredProcess
)其中T:System.ComponentModel.MarshallByValueComponent,new()
{
var da=新的SqlDataAdapter(sql,connectionString);
da.SelectCommand.CommandType=命令类型;
da.SelectCommand.CommandTimeout=0;
foreach(参数中的SqlParameter参数)
{da.SelectCommand.Parameters.Add(Parameter);}
da.Fill(container);//错误:无法从“T”转换为“System.Data.DataTable”
返回容器;
}
但是我得到了上面显示的错误
如果我将容器更改为动态,它将编译。但这似乎是一个黑客。
组合这两个函数的正确方法是什么?因为
DataSet
和DataTable
是完全独立的类,您必须使用不同的SqlDataAdapter重载。填充对于它们中的每一个,您将无法使用通用方法将两个方法简化为一个。但是,您可以使用一种方法来减少重复代码,该方法接受一个委托,该委托定义了在方法过程中如何处理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;
}
公共静态数据表GetDataSet(
SqlParameterHash参数、字符串sql、字符串connectionString、,
CommandType CommandType=CommandType.StoredProcess
)
{
数据集ds=新数据集();
UseDataAdapter(
参数、sql、connectionString、,
da=>da.Fill(ds),commandType
);
返回ds;
}
公共静态数据表GetDataTable(
SqlParameterHash参数、字符串sql、字符串connectionString、,
CommandType CommandType=CommandType.StoredProcess
)
{
DataTable dt=新的DataTable();
UseDataAdapter(
参数、sql、connectionString、,
da=>da.Fill(dt),commandType
);
返回dt;
}
公共静态无效UseDataAdapter(
SqlParameterHash参数、字符串sql、字符串connectionString、,
动作适配器动作,
CommandType CommandType=CommandType.StoredProcess
)
{
SqlConnection连接=新的SqlConnection(connectionString);
connection.Open();
SqlDataAdapter da=新的SqlDataAdapter(sql,连接);
da.SelectCommand.CommandType=命令类型;
da.SelectCommand.CommandTimeout=0;
foreach(参数中的SqlParameter参数)
{da.SelectCommand.Parameters.Add(Parameter);}
自适应作用(da);
da.SelectCommand.Parameters.Clear();
返回dt;
}
您可以添加一个操作
参数来填充您想要支持的每种类型:
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 private T GetDataX(SqlParameterHash参数、字符串sql、字符串connectionString、Action fillAction、CommandType CommandType=CommandType.StoredProcess)
其中T:System.ComponentModel.MarshallByValueComponent,new()
{
SqlConnection连接=新的SqlConnection(connectionString);
connection.Open();
SqlDataAdapter da=新的SqlDataAdapter(sql,连接);
da.SelectCommand.CommandType=命令类型;
da.SelectCommand.CommandTimeout=0;
foreach(参数中的SqlParameter参数)
{da.SelectCommand.Parameters.Add(Parameter);}
T容器=新的T();
填充(容器,da);
da.SelectCommand.Parameters.Clear();
返回容器;
}
然后,您可以根据以下方法编写其他方法:
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);
}
静态公共数据表GetDataTable(SqlParameterHash参数,字符串sql,
字符串连接字符串,CommandType CommandType=CommandType.StoredProcess)
{
返回GetDataX(参数,sql,connectionString,(dt,adapter)=>{adapter.Fill(dt);},commandType);
}
静态公共数据集GetDataSet(SqlParameterHash参数、字符串sql、,
字符串连接字符串,CommandType CommandType=CommandType.StoredProcess)
{
返回GetDataX(参数,sql,connectionString,(ds,适配器)=>{adapter.Fill(ds);},commandType);
}
强制注释:关闭您的连接。或者更好:甚至不要打开它们,让da.Fill()
管理它。非常好的建议。我已经编辑了上面的代码,让da.Fill()管理连接。通常我会同意您的意见,但是使用dynamic
的开销可能会使您的代码慢几个数量级。我认为使用dynamic
就像用大锤敲钉子一样。