public static void DeriveParameters(DbCommand cmd, params object[] values) { AppRuntime.GuardArgument(cmd, "cmd"); AppRuntime.GuardArgument(string.IsNullOrEmpty(cmd.CommandText), "cmd.CommandText"); AppRuntime.GuardArgument(cmd.Connection == null, "cmd.Connection"); AppRuntime.GuardArgument(values, "values"); cmd.CommandType = CommandType.StoredProcedure; string key = "DeriveParameters_" + cmd.CommandText; DbParameter[] discoveredParameters = AppRuntime.Cache[key] as DbParameter[]; if (discoveredParameters == null) { string qualifiedName = cmd.GetType().AssemblyQualifiedName; Type builderType = Type.GetType(qualifiedName.Insert(qualifiedName.IndexOf(','), "Builder")); MethodInfo method = builderType.GetMethod("DeriveParameters", BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod); if (method == null) { throw new ArgumentException("The specified provider factory doesn't support stored procedures."); } bool isClosed = cmd.Connection.State == ConnectionState.Closed; if (isClosed) { cmd.Connection.Open(); } method.Invoke(null, new object[] { cmd }); if (isClosed) { cmd.Connection.Close(); } AppRuntime.Cache[key] = discoveredParameters = new DbParameter[cmd.Parameters.Count]; for (int i = 0; i < discoveredParameters.Length; i++) { (discoveredParameters[i] = cmd.Parameters[i]).Value = DBNull.Value; } cmd.Parameters.Clear(); } //Always discoveredParameters[0].ParameterName == ReturnParameterName AppRuntime.GuardArgument(discoveredParameters.Length - 1 != values.Length, "The number of parameters doesn't match number of values for stored procedures."); if (!cmd.Parameters.Contains(ReturnParameterName)) { cmd.Parameters.Add(((ICloneable)discoveredParameters[0]).Clone()); } for (int i = 0; i < values.Length; i++) { DbParameter cloneParameter = discoveredParameters[i + 1]; int index = cmd.Parameters.IndexOf(cloneParameter.ParameterName); if (index == -1) { object cloned = ((ICloneable)cloneParameter).Clone(); if (!DbUtility.IsNullOrDBNull(values[i])) { ((DbParameter)cloned).Value = values[i]; } cmd.Parameters.Add(cloned); } else { cmd.Parameters[index].Value = values[i] ?? DBNull.Value; } } }