DAL 的通用过程执行方法,包括。参数
Generic procedure execution method for DAL incl. parameters
我正在尝试在数据访问层中创建一个 "generic" 方法,该方法在 Sql 服务器中执行传递的存储过程,并且还获取 Sql 的列表/数组/集合参数,使代码其他部分中存储过程调用的使用更容易(无需关心连接、命令对象等)。
目标是某某。像这样:
int iAffectedRows = dal.RunProcedure("dbo.mySP", parameters);
参数当然应该事先定义,但没有类型。我希望使用 SqlParameterCollection class 的 AddwithValue()
方法创建它们。
看起来不可能,因为 SqlParameterCollection class 无法实例化。看看这个discussion.
有人知道如何创建这个吗?
发送 DbParameterCollection
(SqlParameterCollection
) 不是一个好主意,因为它与您正在尝试的 ADO.NET 基础架构紧密耦合(您已经发现)抽象掉。最好将自己的参数表示映射到方法内部的集合。
你可以这样解决:
public class DataAccess
{
private ConnectionStringSettings _settings;
public DataAccess(ConnectionStringSettings settings)
{
_settings = settings;
}
public int RunProcedure(string name, dynamic parameters)
{
using (var conn = CreateConnection())
using (var command = CreateCommand(conn, name, parameters))
{
return command.ExecuteNonQuery();
}
}
private DbConnection CreateConnection()
{
var factory = DbProviderFactories.GetFactory(_settings.ProviderName);
var connection = factory.CreateConnection();
connection.ConnectionString = _settings.ConnectionString;
connection.Open();
return connection;
}
private DbCommand CreateCommand(DbConnection conn, string commandText,
object parameters)
{
var cmd = conn.CreateCommand();
cmd.CommandText = commandText;
cmd.CommandType = CommandType.StoredProcedure;
foreach(PropertyInfo parameter in parameters.GetType().GetProperties())
{
var commandParameter = cmd.CreateParameter();
commandParameter.ParameterName = "@" + parameter.Name;
commandParameter.Value = parameter.GetValue(parameters);
cmd.Parameters.Add(commandParameter);
}
return cmd;
}
}
可使用如下语法调用:
dal.RunProcedure("dbo.mySP", new {
Parameter1 = value1,
Parameter2 = value2
});
如果只想支持SqlClient
,可以大大简化代码。
但与其自己滚动,不如使用现成的稳定库,例如 Dapper。
我最终得到了以下解决方案:
SqlParameter[] parameters = {
new SqlParameter("@p1", SqlDbType.Int) { Value = 999},
new SqlParameter("@p2", SqlDbType.Char, 30, "source") { Value = "test"}
};
da.RunProcedure("[dbo].[SP1]", parameters, out rowsAffected);
RunProcedure 接受 IDataParameter[] parameters
并将其转发给一个命令生成器方法,该方法将它们中的每一个添加到我的 SqlCommand 对象的 SqlParameters 属性 中:
private static SqlCommand BuildQueryCommand(string storedProcName, IDataParameter[] parameters)
{
SqlCommand command = new SqlCommand( storedProcName, GetDBConnection() );
command.CommandType = CommandType.StoredProcedure;
if (parameters != null)
{
foreach (SqlParameter parameter in parameters)
{
command.Parameters.Add( parameter );
}
}
return command;
}
这很好用,这样我就可以用 1 行代码(这是我的目标#1)添加每个参数,包括。 SqlParameter 的所有属性都可用(如果需要,使用 SqlDBType,这取决于用户)。
我正在尝试在数据访问层中创建一个 "generic" 方法,该方法在 Sql 服务器中执行传递的存储过程,并且还获取 Sql 的列表/数组/集合参数,使代码其他部分中存储过程调用的使用更容易(无需关心连接、命令对象等)。
目标是某某。像这样:
int iAffectedRows = dal.RunProcedure("dbo.mySP", parameters);
参数当然应该事先定义,但没有类型。我希望使用 SqlParameterCollection class 的 AddwithValue()
方法创建它们。
看起来不可能,因为 SqlParameterCollection class 无法实例化。看看这个discussion.
有人知道如何创建这个吗?
发送 DbParameterCollection
(SqlParameterCollection
) 不是一个好主意,因为它与您正在尝试的 ADO.NET 基础架构紧密耦合(您已经发现)抽象掉。最好将自己的参数表示映射到方法内部的集合。
你可以这样解决:
public class DataAccess
{
private ConnectionStringSettings _settings;
public DataAccess(ConnectionStringSettings settings)
{
_settings = settings;
}
public int RunProcedure(string name, dynamic parameters)
{
using (var conn = CreateConnection())
using (var command = CreateCommand(conn, name, parameters))
{
return command.ExecuteNonQuery();
}
}
private DbConnection CreateConnection()
{
var factory = DbProviderFactories.GetFactory(_settings.ProviderName);
var connection = factory.CreateConnection();
connection.ConnectionString = _settings.ConnectionString;
connection.Open();
return connection;
}
private DbCommand CreateCommand(DbConnection conn, string commandText,
object parameters)
{
var cmd = conn.CreateCommand();
cmd.CommandText = commandText;
cmd.CommandType = CommandType.StoredProcedure;
foreach(PropertyInfo parameter in parameters.GetType().GetProperties())
{
var commandParameter = cmd.CreateParameter();
commandParameter.ParameterName = "@" + parameter.Name;
commandParameter.Value = parameter.GetValue(parameters);
cmd.Parameters.Add(commandParameter);
}
return cmd;
}
}
可使用如下语法调用:
dal.RunProcedure("dbo.mySP", new {
Parameter1 = value1,
Parameter2 = value2
});
如果只想支持SqlClient
,可以大大简化代码。
但与其自己滚动,不如使用现成的稳定库,例如 Dapper。
我最终得到了以下解决方案:
SqlParameter[] parameters = {
new SqlParameter("@p1", SqlDbType.Int) { Value = 999},
new SqlParameter("@p2", SqlDbType.Char, 30, "source") { Value = "test"}
};
da.RunProcedure("[dbo].[SP1]", parameters, out rowsAffected);
RunProcedure 接受 IDataParameter[] parameters
并将其转发给一个命令生成器方法,该方法将它们中的每一个添加到我的 SqlCommand 对象的 SqlParameters 属性 中:
private static SqlCommand BuildQueryCommand(string storedProcName, IDataParameter[] parameters)
{
SqlCommand command = new SqlCommand( storedProcName, GetDBConnection() );
command.CommandType = CommandType.StoredProcedure;
if (parameters != null)
{
foreach (SqlParameter parameter in parameters)
{
command.Parameters.Add( parameter );
}
}
return command;
}
这很好用,这样我就可以用 1 行代码(这是我的目标#1)添加每个参数,包括。 SqlParameter 的所有属性都可用(如果需要,使用 SqlDBType,这取决于用户)。