diff --git a/AmalgamationTool/DynamORM.Amalgamation.cs b/AmalgamationTool/DynamORM.Amalgamation.cs
index afd2ab7..a9d936f 100644
--- a/AmalgamationTool/DynamORM.Amalgamation.cs
+++ b/AmalgamationTool/DynamORM.Amalgamation.cs
@@ -2681,6 +2681,24 @@ namespace DynamORM
.ExecuteNonQuery();
}
}
+ /// Execute typed stored procedure descriptor.
+ /// Procedure descriptor type.
+ /// Procedure result.
+ public virtual object Procedure()
+ {
+ return Procedure(null);
+ }
+ /// Execute typed stored procedure descriptor.
+ /// Procedure descriptor type.
+ /// Procedure arguments contract.
+ /// Procedure result.
+ public virtual object Procedure(object args)
+ {
+ if ((Options & DynamicDatabaseOptions.SupportStoredProcedures) != DynamicDatabaseOptions.SupportStoredProcedures)
+ throw new InvalidOperationException("Database connection desn't support stored procedures.");
+
+ return new DynamicProcedureInvoker(this).Exec(args);
+ }
#endregion Procedure
#region Execute
@@ -5331,6 +5349,23 @@ namespace DynamORM
_prefixes = prefixes;
_db = db;
}
+ /// Execute typed stored procedure descriptor.
+ /// Procedure descriptor type.
+ /// Optional procedure arguments contract.
+ /// Procedure result.
+ public virtual object Exec(object args = null)
+ {
+ DynamicProcedureDescriptor descriptor = DynamicProcedureDescriptor.Resolve(typeof(TProcedure));
+ return InvokeProcedure(
+ descriptor.ProcedureName,
+ descriptor.ResultName,
+ new List(),
+ args == null ? new object[0] : new[] { args },
+ new CallInfo(args == null ? 0 : 1),
+ descriptor.ResultType,
+ descriptor.ArgumentsType,
+ descriptor.ProcedureType);
+ }
/// This is where the magic begins.
/// Binder to create owner.
/// Binder invoke result.
@@ -5360,31 +5395,23 @@ namespace DynamORM
// Get generic types
IList types = binder.GetGenericTypeArguments() ?? new List();
- 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 types, object[] args, CallInfo info, Type declaredResultType, Type expectedArgumentsType, Type procedureType)
+ {
+ object result;
+ Dictionary retParams = null;
+
+ if (expectedArgumentsType != null)
{
- if (types.Count != 1)
- throw new InvalidOperationException("Exec(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();
-
if (args.Length > 1)
throw new InvalidOperationException("Exec(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 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;
}
/// Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.
diff --git a/DynamORM.Tests/Procedure/ProcedureParameterBinderTests.cs b/DynamORM.Tests/Procedure/ProcedureParameterBinderTests.cs
index a98f2d7..6036f19 100644
--- a/DynamORM.Tests/Procedure/ProcedureParameterBinderTests.cs
+++ b/DynamORM.Tests/Procedure/ProcedureParameterBinderTests.cs
@@ -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(() =>
{
@@ -162,13 +162,11 @@ namespace DynamORM.Tests.Procedure
}
[Test]
- public void TestExecRejectsMultipleArguments()
+ public void TestDynamicDatabaseTypedProcedureRejectsWrongArgumentsType()
{
- dynamic procedures = new DynamicProcedureInvoker(null);
-
Assert.Throws(() =>
{
- var ignored = procedures.Exec(new ProcedureParameterObject(), new ProcedureParameterObject());
+ var ignored = Database.Procedure(new ProcedureParameterColumnFallbackObject());
});
}
diff --git a/DynamORM/DynamicDatabase.cs b/DynamORM/DynamicDatabase.cs
index 0735cc5..843b5f9 100644
--- a/DynamORM/DynamicDatabase.cs
+++ b/DynamORM/DynamicDatabase.cs
@@ -1232,10 +1232,10 @@ namespace DynamORM
/// Name of stored procedure to execute.
/// Arguments (parameters) in form of expando object.
/// Number of affected rows.
- 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();
+ }
+ }
+
+ /// Execute typed stored procedure descriptor.
+ /// Procedure descriptor type.
+ /// Procedure result.
+ public virtual object Procedure()
+ {
+ return Procedure(null);
+ }
+
+ /// Execute typed stored procedure descriptor.
+ /// Procedure descriptor type.
+ /// Procedure arguments contract.
+ /// Procedure result.
+ public virtual object Procedure(object args)
+ {
+ if ((Options & DynamicDatabaseOptions.SupportStoredProcedures) != DynamicDatabaseOptions.SupportStoredProcedures)
+ throw new InvalidOperationException("Database connection desn't support stored procedures.");
+
+ return new DynamicProcedureInvoker(this).Exec(args);
+ }
+
+ #endregion Procedure
#region Execute
diff --git a/DynamORM/DynamicProcedureInvoker.cs b/DynamORM/DynamicProcedureInvoker.cs
index 068115d..4192bb1 100644
--- a/DynamORM/DynamicProcedureInvoker.cs
+++ b/DynamORM/DynamicProcedureInvoker.cs
@@ -57,11 +57,29 @@ namespace DynamORM
private List _prefixes;
private bool _isDisposed;
- internal DynamicProcedureInvoker(DynamicDatabase db, List prefixes = null)
- {
- _prefixes = prefixes;
- _db = db;
- }
+ internal DynamicProcedureInvoker(DynamicDatabase db, List prefixes = null)
+ {
+ _prefixes = prefixes;
+ _db = db;
+ }
+
+ /// Execute typed stored procedure descriptor.
+ /// Procedure descriptor type.
+ /// Optional procedure arguments contract.
+ /// Procedure result.
+ public virtual object Exec(object args = null)
+ {
+ DynamicProcedureDescriptor descriptor = DynamicProcedureDescriptor.Resolve(typeof(TProcedure));
+ return InvokeProcedure(
+ descriptor.ProcedureName,
+ descriptor.ResultName,
+ new List(),
+ args == null ? new object[0] : new[] { args },
+ new CallInfo(args == null ? 0 : 1),
+ descriptor.ResultType,
+ descriptor.ArgumentsType,
+ descriptor.ProcedureType);
+ }
/// This is where the magic begins.
/// Binder to create owner.
@@ -93,35 +111,28 @@ namespace DynamORM
// Get generic types
IList types = binder.GetGenericTypeArguments() ?? new List();
- 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 types, object[] args, CallInfo info, Type declaredResultType, Type expectedArgumentsType, Type procedureType)
+ {
+ object result;
+ Dictionary retParams = null;
+
+ if (expectedArgumentsType != null)
{
- if (types.Count != 1)
- throw new InvalidOperationException("Exec(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();
-
if (args.Length > 1)
throw new InvalidOperationException("Exec(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 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;
+ }
/// Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.