Expose typed procedure execution as explicit APIs
This commit is contained in:
@@ -2681,6 +2681,24 @@ namespace DynamORM
|
|||||||
.ExecuteNonQuery();
|
.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
|
#endregion Procedure
|
||||||
|
|
||||||
#region Execute
|
#region Execute
|
||||||
@@ -5331,6 +5349,23 @@ namespace DynamORM
|
|||||||
_prefixes = prefixes;
|
_prefixes = prefixes;
|
||||||
_db = db;
|
_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>
|
/// <summary>This is where the magic begins.</summary>
|
||||||
/// <param name="binder">Binder to create owner.</param>
|
/// <param name="binder">Binder to create owner.</param>
|
||||||
/// <param name="result">Binder invoke result.</param>
|
/// <param name="result">Binder invoke result.</param>
|
||||||
@@ -5360,31 +5395,23 @@ namespace DynamORM
|
|||||||
|
|
||||||
// Get generic types
|
// Get generic types
|
||||||
IList<Type> types = binder.GetGenericTypeArguments() ?? new List<Type>();
|
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)
|
if (args.Length > 1)
|
||||||
throw new InvalidOperationException("Exec<TProcedure>(args) accepts at most one arguments contract instance.");
|
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()))
|
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}'.", descriptor.ProcedureType.FullName, execArgumentsType.FullName, args[0].GetType().FullName));
|
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 (IDbConnection con = _db.Open())
|
||||||
using (IDbCommand cmd = con.CreateCommand())
|
using (IDbCommand cmd = con.CreateCommand())
|
||||||
{
|
{
|
||||||
@@ -5740,7 +5767,7 @@ namespace DynamORM
|
|||||||
|
|
||||||
#endregion Handle out params
|
#endregion Handle out params
|
||||||
}
|
}
|
||||||
return true;
|
return result;
|
||||||
}
|
}
|
||||||
/// <summary>Performs application-defined tasks associated with
|
/// <summary>Performs application-defined tasks associated with
|
||||||
/// freeing, releasing, or resetting unmanaged resources.</summary>
|
/// freeing, releasing, or resetting unmanaged resources.</summary>
|
||||||
|
|||||||
@@ -151,9 +151,9 @@ namespace DynamORM.Tests.Procedure
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestExecRejectsWrongArgumentsType()
|
public void TestExecMethodRejectsWrongArgumentsType()
|
||||||
{
|
{
|
||||||
dynamic procedures = new DynamicProcedureInvoker(null);
|
var procedures = new DynamicProcedureInvoker(null);
|
||||||
|
|
||||||
Assert.Throws<System.InvalidOperationException>(() =>
|
Assert.Throws<System.InvalidOperationException>(() =>
|
||||||
{
|
{
|
||||||
@@ -162,13 +162,11 @@ namespace DynamORM.Tests.Procedure
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestExecRejectsMultipleArguments()
|
public void TestDynamicDatabaseTypedProcedureRejectsWrongArgumentsType()
|
||||||
{
|
{
|
||||||
dynamic procedures = new DynamicProcedureInvoker(null);
|
|
||||||
|
|
||||||
Assert.Throws<System.InvalidOperationException>(() =>
|
Assert.Throws<System.InvalidOperationException>(() =>
|
||||||
{
|
{
|
||||||
var ignored = procedures.Exec<ExecProcedureDescriptor>(new ProcedureParameterObject(), new ProcedureParameterObject());
|
var ignored = Database.Procedure<ExecProcedureDescriptor>(new ProcedureParameterColumnFallbackObject());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1247,6 +1247,26 @@ namespace DynamORM
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <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
|
#endregion Procedure
|
||||||
|
|
||||||
#region Execute
|
#region Execute
|
||||||
|
|||||||
@@ -63,6 +63,24 @@ namespace DynamORM
|
|||||||
_db = db;
|
_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>
|
/// <summary>This is where the magic begins.</summary>
|
||||||
/// <param name="binder">Binder to create owner.</param>
|
/// <param name="binder">Binder to create owner.</param>
|
||||||
/// <param name="result">Binder invoke result.</param>
|
/// <param name="result">Binder invoke result.</param>
|
||||||
@@ -93,32 +111,25 @@ namespace DynamORM
|
|||||||
|
|
||||||
// Get generic types
|
// Get generic types
|
||||||
IList<Type> types = binder.GetGenericTypeArguments() ?? new List<Type>();
|
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)
|
if (args.Length > 1)
|
||||||
throw new InvalidOperationException("Exec<TProcedure>(args) accepts at most one arguments contract instance.");
|
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()))
|
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}'.", descriptor.ProcedureType.FullName, execArgumentsType.FullName, args[0].GetType().FullName));
|
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 (IDbConnection con = _db.Open())
|
||||||
using (IDbCommand cmd = con.CreateCommand())
|
using (IDbCommand cmd = con.CreateCommand())
|
||||||
{
|
{
|
||||||
@@ -488,7 +499,7 @@ namespace DynamORM
|
|||||||
#endregion Handle out params
|
#endregion Handle out params
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Performs application-defined tasks associated with
|
/// <summary>Performs application-defined tasks associated with
|
||||||
|
|||||||
Reference in New Issue
Block a user