DAL的通用程序执行方法参数

时间:2015-12-15 15:05:16

标签: stored-procedures ado.net data-access-layer sqlparameter

我正在尝试创建一个"泛型"数据访问层中的方法,它在Sql Server中执行传递的存储过程,并且还获取SqlParameters的列表/数组/集合,以便在代码的其他部分中使用存储过程调用更容易(无需关心连接,命令对象等)。

目标是......像这样:

int iAffectedRows = dal.RunProcedure("dbo.mySP", parameters);

参数当然应该先前定义,但没有类型。我希望使用SqlParameterCollection classAddwithValue()方法创建它们。

看起来它是不可能的,因为SqlParameterCollection类无法实现。看看这个discussion

任何人都知道如何创建它?

2 个答案:

答案 0 :(得分:1)

发送DbParameterCollectionSqlParameterCollection)并不是一个好主意,因为它与您尝试抽象的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

答案 1 :(得分:1)

我最终得到了以下解决方案:

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

这很好用,这样我可以添加每个Param一行代码(这是我的目的地#1)incl。可用的所有SqlParameter属性(如果需要,使用SqlDBType,这取决于用户)。