diff --git a/CodeOnlyStoredProcedure-NET40/CodeOnlyStoredProcedure-NET40.csproj b/CodeOnlyStoredProcedure-NET40/CodeOnlyStoredProcedure-NET40.csproj
index 2d9427d..015f055 100644
--- a/CodeOnlyStoredProcedure-NET40/CodeOnlyStoredProcedure-NET40.csproj
+++ b/CodeOnlyStoredProcedure-NET40/CodeOnlyStoredProcedure-NET40.csproj
@@ -129,6 +129,7 @@
+
diff --git a/CodeOnlyStoredProcedure/CodeOnlyStoredProcedure.csproj b/CodeOnlyStoredProcedure/CodeOnlyStoredProcedure.csproj
index 4d85823..99a129c 100644
--- a/CodeOnlyStoredProcedure/CodeOnlyStoredProcedure.csproj
+++ b/CodeOnlyStoredProcedure/CodeOnlyStoredProcedure.csproj
@@ -119,6 +119,7 @@
+
diff --git a/CodeOnlyStoredProcedure/Dynamic/DynamicStoredProcedure.cs b/CodeOnlyStoredProcedure/Dynamic/DynamicStoredProcedure.cs
index 4f9c139..a28520f 100644
--- a/CodeOnlyStoredProcedure/Dynamic/DynamicStoredProcedure.cs
+++ b/CodeOnlyStoredProcedure/Dynamic/DynamicStoredProcedure.cs
@@ -134,6 +134,8 @@ public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, o
attr.Schema));
}
}
+ else if (argType == typeof(DataTable))
+ parameters.Add(new TableValuedParameter(parmName, (DataTable)arg));
else if (dbType == DbType.Object)
parameters.AddRange(argType.GetParameters(arg));
else if (direction == ParameterDirection.Output)
diff --git a/CodeOnlyStoredProcedure/StoredProcedureExtensions.WithTableValuedParameter.cs b/CodeOnlyStoredProcedure/StoredProcedureExtensions.WithTableValuedParameter.cs
index 141b745..282bc65 100644
--- a/CodeOnlyStoredProcedure/StoredProcedureExtensions.WithTableValuedParameter.cs
+++ b/CodeOnlyStoredProcedure/StoredProcedureExtensions.WithTableValuedParameter.cs
@@ -88,5 +88,87 @@ public static TSP WithTableValuedParameter(this TSP sp,
return (TSP)sp.CloneWith(new TableValuedParameter(name, table, typeof(TRow), tableTypeName, tableTypeSchema));
}
+
+ ///
+ /// Clones the given , and associates the items
+ /// as a Table Valued Parameter.
+ ///
+ /// The type of to associate the Table Valued Parameter with.
+ /// The to clone.
+ /// The name of the Table Valued Parameter in the stored procedure.
+ /// The to pass in the Table Valued Parameter. Make sure the is set,
+ /// as that will be used to identify the TVP's type in the database.
+ /// A copy of the that has the Table Valued Parameter set.
+ /// StoredProcedures are immutable, so all the Fluent API methods return copies.
+ public static TSP WithTableValuedParameter(this TSP sp,
+ string name,
+ DataTable table)
+ where TSP : StoredProcedure
+ {
+ Contract.Requires(sp != null);
+ Contract.Requires(!string.IsNullOrWhiteSpace(name));
+ Contract.Requires(table != null);
+ Contract.Ensures(Contract.Result() != null);
+
+ return (TSP)sp.CloneWith(new TableValuedParameter(name, table));
+ }
+
+ ///
+ /// Clones the given , and associates the items
+ /// as a Table Valued Parameter.
+ ///
+ /// The type of to associate the Table Valued Parameter with.
+ /// The to clone.
+ /// The name of the Table Valued Parameter in the stored procedure.
+ /// The to pass in the Table Valued Parameter.
+ /// The name of the table that the database's stored procedure expects
+ /// in its Table Valued Parameter.
+ /// A copy of the that has the Table Valued Parameter set.
+ /// StoredProcedures are immutable, so all the Fluent API methods return copies.
+ public static TSP WithTableValuedParameter(this TSP sp,
+ string name,
+ DataTable table,
+ string tableTypeName)
+ where TSP : StoredProcedure
+ {
+ Contract.Requires(sp != null);
+ Contract.Requires(!string.IsNullOrWhiteSpace(name));
+ Contract.Requires(table != null);
+ Contract.Requires(!string.IsNullOrWhiteSpace(tableTypeName));
+ Contract.Ensures(Contract.Result() != null);
+
+ return (TSP)sp.CloneWith(new TableValuedParameter(name, table, tableTypeName));
+ }
+
+ ///
+ /// Clones the given , and associates the items
+ /// as a Table Valued Parameter.
+ ///
+ /// The type of to associate the Table Valued Parameter with.
+ /// The to clone.
+ /// The name of the Table Valued Parameter in the stored procedure.
+ /// The to pass in the Table Valued Parameter.
+ /// The schema of the table that the database's stored procedure expects
+ /// in its Table Valued Parameter.
+ /// The name of the table that the database's stored procedure expects
+ /// in its Table Valued Parameter.
+ /// A copy of the that has the Table Valued Parameter set.
+ /// StoredProcedures are immutable, so all the Fluent API methods return copies.
+ public static TSP WithTableValuedParameter(this TSP sp,
+ string name,
+ DataTable table,
+ string tableTypeSchema,
+ string tableTypeName)
+ where TSP : StoredProcedure
+ {
+ Contract.Requires(sp != null);
+ Contract.Requires(!string.IsNullOrWhiteSpace(name));
+ Contract.Requires(table != null);
+ Contract.Requires(!string.IsNullOrWhiteSpace(tableTypeSchema));
+ Contract.Requires(!string.IsNullOrWhiteSpace(tableTypeName));
+ Contract.Ensures(Contract.Result() != null);
+
+ return (TSP)sp.CloneWith(new TableValuedParameter(name, table, tableTypeName, tableTypeSchema));
+ }
}
}
diff --git a/CodeOnlyStoredProcedure/StoredProcedureParameters/TableValuedParameter.cs b/CodeOnlyStoredProcedure/StoredProcedureParameters/TableValuedParameter.cs
index 6324b5b..a767b8b 100644
--- a/CodeOnlyStoredProcedure/StoredProcedureParameters/TableValuedParameter.cs
+++ b/CodeOnlyStoredProcedure/StoredProcedureParameters/TableValuedParameter.cs
@@ -13,11 +13,38 @@ internal class TableValuedParameter : IInputStoredProcedureParameter
{
private readonly IEnumerable values;
private readonly Type valueType;
+ private readonly DataTable data;
public string ParameterName { get; }
- public object Value { get { return values; } }
+ public object Value { get { return data as object ?? values; } }
+
internal string TypeName { get; }
+ public TableValuedParameter(string name, DataTable data)
+ {
+ Contract.Requires(!string.IsNullOrWhiteSpace(name));
+ Contract.Requires(data != null);
+
+ if (string.IsNullOrWhiteSpace(data.TableName))
+ throw new NotSupportedException("When passing a DataTable, either set its TypeName to the TVP's type, or pass it in as one of the parameters.");
+
+ ParameterName = name;
+ this.data = data;
+ this.TypeName = data.TableName;
+ }
+
+ public TableValuedParameter(string name, DataTable data, string tableTypeName, string tableTypeSchema = "dbo")
+ {
+ Contract.Requires(!string.IsNullOrWhiteSpace(name));
+ Contract.Requires(data != null);
+ Contract.Requires(!string.IsNullOrWhiteSpace(tableTypeName));
+ Contract.Requires(!string.IsNullOrWhiteSpace(tableTypeSchema));
+
+ ParameterName = name;
+ this.data = data;
+ this.TypeName = $"[{tableTypeSchema}].[{tableTypeName}]";
+ }
+
public TableValuedParameter(string name, IEnumerable values, Type valueType, string tableTypeName, string tableTypeSchema = "dbo")
{
Contract.Requires(!string.IsNullOrWhiteSpace(name));
@@ -43,7 +70,9 @@ public IDbDataParameter CreateDbDataParameter(IDbCommand command)
parm.SqlDbType = SqlDbType.Structured;
parm.TypeName = TypeName;
- if (values.Cast