It's not a good idea to send in a DbParameterCollection
(SqlParameterCollection
), since it's tightly coupled (which you have discovered) with the ADO.NET infrastructure that you're trying to abstract away. It's better to map your own parameter representation to the collection inside your method.
You can solve it using something like this:
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;
}
}
Callable with a syntax like this:
dal.RunProcedure("dbo.mySP", new {
Parameter1 = value1,
Parameter2 = value2
});
You can greatly simplify the code if you only want to support SqlClient
.
But instead of rolling this on your own, use a ready made stable library, such as Dapper.