Expose typed procedure execution as explicit APIs
This commit is contained in:
@@ -2681,6 +2681,24 @@ namespace DynamORM
|
||||
.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
/// <summary>Execute typed stored procedure descriptor.</summary>
|
||||
/// <typeparam name="TProcedure">Procedure descriptor type.</typeparam>
|
||||
/// <returns>Procedure result.</returns>
|
||||
public virtual object Procedure<TProcedure>()
|
||||
{
|
||||
return Procedure<TProcedure>(null);
|
||||
}
|
||||
/// <summary>Execute typed stored procedure descriptor.</summary>
|
||||
/// <typeparam name="TProcedure">Procedure descriptor type.</typeparam>
|
||||
/// <param name="args">Procedure arguments contract.</param>
|
||||
/// <returns>Procedure result.</returns>
|
||||
public virtual object Procedure<TProcedure>(object args)
|
||||
{
|
||||
if ((Options & DynamicDatabaseOptions.SupportStoredProcedures) != DynamicDatabaseOptions.SupportStoredProcedures)
|
||||
throw new InvalidOperationException("Database connection desn't support stored procedures.");
|
||||
|
||||
return new DynamicProcedureInvoker(this).Exec<TProcedure>(args);
|
||||
}
|
||||
#endregion Procedure
|
||||
|
||||
#region Execute
|
||||
@@ -5331,6 +5349,23 @@ namespace DynamORM
|
||||
_prefixes = prefixes;
|
||||
_db = db;
|
||||
}
|
||||
/// <summary>Execute typed stored procedure descriptor.</summary>
|
||||
/// <typeparam name="TProcedure">Procedure descriptor type.</typeparam>
|
||||
/// <param name="args">Optional procedure arguments contract.</param>
|
||||
/// <returns>Procedure result.</returns>
|
||||
public virtual object Exec<TProcedure>(object args = null)
|
||||
{
|
||||
DynamicProcedureDescriptor descriptor = DynamicProcedureDescriptor.Resolve(typeof(TProcedure));
|
||||
return InvokeProcedure(
|
||||
descriptor.ProcedureName,
|
||||
descriptor.ResultName,
|
||||
new List<Type>(),
|
||||
args == null ? new object[0] : new[] { args },
|
||||
new CallInfo(args == null ? 0 : 1),
|
||||
descriptor.ResultType,
|
||||
descriptor.ArgumentsType,
|
||||
descriptor.ProcedureType);
|
||||
}
|
||||
/// <summary>This is where the magic begins.</summary>
|
||||
/// <param name="binder">Binder to create owner.</param>
|
||||
/// <param name="result">Binder invoke result.</param>
|
||||
@@ -5360,31 +5395,23 @@ namespace DynamORM
|
||||
|
||||
// Get generic types
|
||||
IList<Type> types = binder.GetGenericTypeArguments() ?? new List<Type>();
|
||||
Type declaredResultType = null;
|
||||
string procedureName = binder.Name;
|
||||
string resultName = binder.Name;
|
||||
Type execArgumentsType = null;
|
||||
|
||||
if (binder.Name == "Exec")
|
||||
result = InvokeProcedure(binder.Name, binder.Name, types, args, info, null, null, null);
|
||||
return true;
|
||||
}
|
||||
internal object InvokeProcedure(string procedureName, string resultName, IList<Type> types, object[] args, CallInfo info, Type declaredResultType, Type expectedArgumentsType, Type procedureType)
|
||||
{
|
||||
object result;
|
||||
Dictionary<string, int> retParams = null;
|
||||
|
||||
if (expectedArgumentsType != null)
|
||||
{
|
||||
if (types.Count != 1)
|
||||
throw new InvalidOperationException("Exec<TProcedure>(args) requires exactly one generic procedure descriptor type.");
|
||||
|
||||
DynamicProcedureDescriptor descriptor = DynamicProcedureDescriptor.Resolve(types[0]);
|
||||
procedureName = descriptor.ProcedureName;
|
||||
resultName = descriptor.ResultName;
|
||||
execArgumentsType = descriptor.ArgumentsType;
|
||||
declaredResultType = descriptor.ResultType;
|
||||
types = new List<Type>();
|
||||
|
||||
if (args.Length > 1)
|
||||
throw new InvalidOperationException("Exec<TProcedure>(args) accepts at most one arguments contract instance.");
|
||||
|
||||
if (args.Length == 1 && args[0] != null && !execArgumentsType.IsAssignableFrom(args[0].GetType()))
|
||||
throw new InvalidOperationException(string.Format("Exec<{0}>(args) expects argument of type '{1}', received '{2}'.", descriptor.ProcedureType.FullName, execArgumentsType.FullName, args[0].GetType().FullName));
|
||||
if (args.Length == 1 && args[0] != null && !expectedArgumentsType.IsAssignableFrom(args[0].GetType()))
|
||||
throw new InvalidOperationException(string.Format("Exec<{0}>(args) expects argument of type '{1}', received '{2}'.", procedureType == null ? expectedArgumentsType.FullName : procedureType.FullName, expectedArgumentsType.FullName, args[0].GetType().FullName));
|
||||
}
|
||||
Dictionary<string, int> retParams = null;
|
||||
|
||||
using (IDbConnection con = _db.Open())
|
||||
using (IDbCommand cmd = con.CreateCommand())
|
||||
{
|
||||
@@ -5740,7 +5767,7 @@ namespace DynamORM
|
||||
|
||||
#endregion Handle out params
|
||||
}
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
/// <summary>Performs application-defined tasks associated with
|
||||
/// freeing, releasing, or resetting unmanaged resources.</summary>
|
||||
|
||||
@@ -151,9 +151,9 @@ namespace DynamORM.Tests.Procedure
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestExecRejectsWrongArgumentsType()
|
||||
public void TestExecMethodRejectsWrongArgumentsType()
|
||||
{
|
||||
dynamic procedures = new DynamicProcedureInvoker(null);
|
||||
var procedures = new DynamicProcedureInvoker(null);
|
||||
|
||||
Assert.Throws<System.InvalidOperationException>(() =>
|
||||
{
|
||||
@@ -162,13 +162,11 @@ namespace DynamORM.Tests.Procedure
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestExecRejectsMultipleArguments()
|
||||
public void TestDynamicDatabaseTypedProcedureRejectsWrongArgumentsType()
|
||||
{
|
||||
dynamic procedures = new DynamicProcedureInvoker(null);
|
||||
|
||||
Assert.Throws<System.InvalidOperationException>(() =>
|
||||
{
|
||||
var ignored = procedures.Exec<ExecProcedureDescriptor>(new ProcedureParameterObject(), new ProcedureParameterObject());
|
||||
var ignored = Database.Procedure<ExecProcedureDescriptor>(new ProcedureParameterColumnFallbackObject());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1232,10 +1232,10 @@ namespace DynamORM
|
||||
/// <param name="procName">Name of stored procedure to execute.</param>
|
||||
/// <param name="args">Arguments (parameters) in form of expando object.</param>
|
||||
/// <returns>Number of affected rows.</returns>
|
||||
public virtual int Procedure(string procName, ExpandoObject args)
|
||||
{
|
||||
if ((Options & DynamicDatabaseOptions.SupportStoredProcedures) != DynamicDatabaseOptions.SupportStoredProcedures)
|
||||
throw new InvalidOperationException("Database connection desn't support stored procedures.");
|
||||
public virtual int Procedure(string procName, ExpandoObject args)
|
||||
{
|
||||
if ((Options & DynamicDatabaseOptions.SupportStoredProcedures) != DynamicDatabaseOptions.SupportStoredProcedures)
|
||||
throw new InvalidOperationException("Database connection desn't support stored procedures.");
|
||||
|
||||
using (IDbConnection con = Open())
|
||||
using (IDbCommand cmd = con.CreateCommand())
|
||||
@@ -1243,11 +1243,31 @@ namespace DynamORM
|
||||
return cmd
|
||||
.SetCommand(CommandType.StoredProcedure, procName)
|
||||
.AddParameters(this, args)
|
||||
.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Procedure
|
||||
.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Execute typed stored procedure descriptor.</summary>
|
||||
/// <typeparam name="TProcedure">Procedure descriptor type.</typeparam>
|
||||
/// <returns>Procedure result.</returns>
|
||||
public virtual object Procedure<TProcedure>()
|
||||
{
|
||||
return Procedure<TProcedure>(null);
|
||||
}
|
||||
|
||||
/// <summary>Execute typed stored procedure descriptor.</summary>
|
||||
/// <typeparam name="TProcedure">Procedure descriptor type.</typeparam>
|
||||
/// <param name="args">Procedure arguments contract.</param>
|
||||
/// <returns>Procedure result.</returns>
|
||||
public virtual object Procedure<TProcedure>(object args)
|
||||
{
|
||||
if ((Options & DynamicDatabaseOptions.SupportStoredProcedures) != DynamicDatabaseOptions.SupportStoredProcedures)
|
||||
throw new InvalidOperationException("Database connection desn't support stored procedures.");
|
||||
|
||||
return new DynamicProcedureInvoker(this).Exec<TProcedure>(args);
|
||||
}
|
||||
|
||||
#endregion Procedure
|
||||
|
||||
#region Execute
|
||||
|
||||
|
||||
@@ -57,11 +57,29 @@ namespace DynamORM
|
||||
private List<string> _prefixes;
|
||||
private bool _isDisposed;
|
||||
|
||||
internal DynamicProcedureInvoker(DynamicDatabase db, List<string> prefixes = null)
|
||||
{
|
||||
_prefixes = prefixes;
|
||||
_db = db;
|
||||
}
|
||||
internal DynamicProcedureInvoker(DynamicDatabase db, List<string> prefixes = null)
|
||||
{
|
||||
_prefixes = prefixes;
|
||||
_db = db;
|
||||
}
|
||||
|
||||
/// <summary>Execute typed stored procedure descriptor.</summary>
|
||||
/// <typeparam name="TProcedure">Procedure descriptor type.</typeparam>
|
||||
/// <param name="args">Optional procedure arguments contract.</param>
|
||||
/// <returns>Procedure result.</returns>
|
||||
public virtual object Exec<TProcedure>(object args = null)
|
||||
{
|
||||
DynamicProcedureDescriptor descriptor = DynamicProcedureDescriptor.Resolve(typeof(TProcedure));
|
||||
return InvokeProcedure(
|
||||
descriptor.ProcedureName,
|
||||
descriptor.ResultName,
|
||||
new List<Type>(),
|
||||
args == null ? new object[0] : new[] { args },
|
||||
new CallInfo(args == null ? 0 : 1),
|
||||
descriptor.ResultType,
|
||||
descriptor.ArgumentsType,
|
||||
descriptor.ProcedureType);
|
||||
}
|
||||
|
||||
/// <summary>This is where the magic begins.</summary>
|
||||
/// <param name="binder">Binder to create owner.</param>
|
||||
@@ -93,35 +111,28 @@ namespace DynamORM
|
||||
|
||||
// Get generic types
|
||||
IList<Type> types = binder.GetGenericTypeArguments() ?? new List<Type>();
|
||||
Type declaredResultType = null;
|
||||
string procedureName = binder.Name;
|
||||
string resultName = binder.Name;
|
||||
Type execArgumentsType = null;
|
||||
|
||||
if (binder.Name == "Exec")
|
||||
result = InvokeProcedure(binder.Name, binder.Name, types, args, info, null, null, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
internal object InvokeProcedure(string procedureName, string resultName, IList<Type> types, object[] args, CallInfo info, Type declaredResultType, Type expectedArgumentsType, Type procedureType)
|
||||
{
|
||||
object result;
|
||||
Dictionary<string, int> retParams = null;
|
||||
|
||||
if (expectedArgumentsType != null)
|
||||
{
|
||||
if (types.Count != 1)
|
||||
throw new InvalidOperationException("Exec<TProcedure>(args) requires exactly one generic procedure descriptor type.");
|
||||
|
||||
DynamicProcedureDescriptor descriptor = DynamicProcedureDescriptor.Resolve(types[0]);
|
||||
procedureName = descriptor.ProcedureName;
|
||||
resultName = descriptor.ResultName;
|
||||
execArgumentsType = descriptor.ArgumentsType;
|
||||
declaredResultType = descriptor.ResultType;
|
||||
types = new List<Type>();
|
||||
|
||||
if (args.Length > 1)
|
||||
throw new InvalidOperationException("Exec<TProcedure>(args) accepts at most one arguments contract instance.");
|
||||
|
||||
if (args.Length == 1 && args[0] != null && !execArgumentsType.IsAssignableFrom(args[0].GetType()))
|
||||
throw new InvalidOperationException(string.Format("Exec<{0}>(args) expects argument of type '{1}', received '{2}'.", descriptor.ProcedureType.FullName, execArgumentsType.FullName, args[0].GetType().FullName));
|
||||
if (args.Length == 1 && args[0] != null && !expectedArgumentsType.IsAssignableFrom(args[0].GetType()))
|
||||
throw new InvalidOperationException(string.Format("Exec<{0}>(args) expects argument of type '{1}', received '{2}'.", procedureType == null ? expectedArgumentsType.FullName : procedureType.FullName, expectedArgumentsType.FullName, args[0].GetType().FullName));
|
||||
}
|
||||
|
||||
Dictionary<string, int> retParams = null;
|
||||
|
||||
using (IDbConnection con = _db.Open())
|
||||
using (IDbCommand cmd = con.CreateCommand())
|
||||
{
|
||||
{
|
||||
if (_prefixes == null || _prefixes.Count == 0)
|
||||
cmd.SetCommand(CommandType.StoredProcedure, procedureName);
|
||||
else
|
||||
@@ -484,12 +495,12 @@ namespace DynamORM
|
||||
result = DynamicProcedureResultBinder.BindPayload(declaredResultType, resultName, mainResult, null);
|
||||
else
|
||||
result = mainResult;
|
||||
|
||||
#endregion Handle out params
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion Handle out params
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>Performs application-defined tasks associated with
|
||||
/// freeing, releasing, or resetting unmanaged resources.</summary>
|
||||
|
||||
Reference in New Issue
Block a user