using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; namespace RDH.Data { public class DynamicParameters : IDynamicParameters { static Dictionary> paramReaderCache = new Dictionary>(); Dictionary parameters = new Dictionary(); List templates; class ParamInfo { public string Name { get; set; } public object Value { get; set; } public ParameterDirection ParameterDirection { get; set; } public DbType? DbType { get; set; } public int? Size { get; set; } public IDbDataParameter AttachedParam { get; set; } } public DynamicParameters() { } public DynamicParameters(object template) { if (template != null) { AddDynamicParams(template); } } /// /// Append a whole object full of params to the dynamic /// EG: AddParams(new {A = 1, B = 2}) // will add property A and B to the dynamic /// /// public void AddDynamicParams( #if CSHARP30 object param #else dynamic param #endif ) { object obj = param as object; if (obj != null) { templates = templates ?? new List(); templates.Add(obj); } } public void Add( #if CSHARP30 string name, object value, DbType? dbType, ParameterDirection? direction, int? size #else string name, object value = null, DbType? dbType = null, ParameterDirection? direction = null, int? size = null #endif ) { parameters[Clean(name)] = new ParamInfo() { Name = name, Value = value, ParameterDirection = direction ?? ParameterDirection.Input, DbType = dbType, Size = size }; } static string Clean(string name) { if (!string.IsNullOrEmpty(name)) { switch (name[0]) { case '@': case ':': case '?': return name.Substring(1); } } return name; } void IDynamicParameters.AddParameters(IDbCommand command, Identity identity) { if (templates != null) { foreach (var template in templates) { var newIdent = identity.ForDynamicParameters(template.GetType()); Action appender; lock (paramReaderCache) { if (!paramReaderCache.TryGetValue(newIdent, out appender)) { appender = SqlMapper.CreateParamInfoGenerator(newIdent); paramReaderCache[newIdent] = appender; } } appender(command, template); } } foreach (var param in parameters.Values) { var p = command.CreateParameter(); var val = param.Value; p.ParameterName = param.Name; p.Value = val ?? DBNull.Value; p.Direction = param.ParameterDirection; var s = val as string; if (s != null) { if (s.Length <= 4000) { p.Size = 4000; } } if (param.Size != null) { p.Size = param.Size.Value; } if (param.DbType != null) { p.DbType = param.DbType.Value; } command.Parameters.Add(p); param.AttachedParam = p; } } public T Get(string name) { var val = parameters[Clean(name)].AttachedParam.Value; if (val == DBNull.Value) { if (default(T) != null) { throw new ApplicationException("Attempting to cast a DBNull to a non nullable type!"); } return default(T); } return (T)val; } } }