I'm trying to call a stored procedure that accepts a table value parameter.  I know that this isn't directly supported in Entity Framework yet but from what I understand you can do it using the ExecuteStoreQuery command off of the ObjectContext.  I have a generic entity framework repository where I have the following ExecuteStoredProcedure method:
public IEnumerable<T> ExecuteStoredProcedure<T>(string procedureName, params object[] parameters) {     StringBuilder command = new StringBuilder();     command.Append("EXEC ");     command.Append(procedureName);     command.Append(" ");      // Add a placeholder for each parameter passed in     for (int i = 0; i < parameters.Length; i++)     {         if (i > 0)             command.Append(",");          command.Append("{" + i + "}");     }      return this.context.ExecuteStoreQuery<T>(command.ToString(), parameters); }   The command string ends up like this:
EXEC someStoredProcedureName {0},{1},{2},{3},{4},{5},{6},{7}   I tried to run this method on a stored procedure that accepts a table valued parameter and it breaks.  I read here that the parameters needed to be of type SqlParameter and the table valued parameter needs to have the SqlDbType set to Structured.  So I did this and I get an error stating:
The table type parameter p6 must have a valid type name   So, I set the SqlParameter.TypeName to the name of the user defined type I created on the database and then when I run the query I get the following truly helpful error:
Incorrect syntax near '0'.   I can get the query to run if I revert back to ADO.NET and and execute a data reader but I was hoping to get it to work using the data context.
Is there a way to pass a table value parameter using ExecuteStoreQuery?  Also, I am actually using Entity Framework Code First and casting the DbContext to an ObjectContext to get the ExecuteStoreQuery method available.  Is this necessary or can I do this against the DbContext as well?
Table-Valued Parameters aka TVPs are commonly used to pass a table as a parameter into stored procedures or functions. They are helpful in a way, we can use a table as an input to these routines and we can get rid of dealing more complex steps to achieve this process.
Table-valued parameters are declared by using user-defined table types. You can use table-valued parameters to send multiple rows of data to a Transact-SQL statement or a routine, such as a stored procedure or function, without creating a temporary table or many parameters.
Step 1 − Select the Console Application from the middle pane and enter TableValuedFunctionDemo in the name field. Step 2 − In Server explorer right-click on your database. Step 3 − Select New Query and enter the following code in T-SQL editor to add a new table in your database.
UPDATE
I've added support for this on Nuget Package - https://github.com/Fodsuk/EntityFrameworkExtras#nuget (EF4,EF5,EF6)
Check out the GitHub repository for code examples.
Slightly off question, but none the less useful for people trying to pass user-defined tables into a stored procedure. After playing around with Nick's example and other Stackoverflow posts, I came up with this:
class Program {     static void Main(string[] args)     {         var entities = new NewBusinessEntities();          var dt = new DataTable();         dt.Columns.Add("WarningCode");         dt.Columns.Add("StatusID");         dt.Columns.Add("DecisionID");         dt.Columns.Add("Criticality");          dt.Rows.Add("EO01", 9, 4, 0);         dt.Rows.Add("EO00", 9, 4, 0);         dt.Rows.Add("EO02", 9, 4, 0);          var caseId = new SqlParameter("caseid", SqlDbType.Int);         caseId.Value = 1;          var userId = new SqlParameter("userid", SqlDbType.UniqueIdentifier);         userId.Value = Guid.Parse("846454D9-DE72-4EF4-ABE2-16EC3710EA0F");          var warnings = new SqlParameter("warnings", SqlDbType.Structured);         warnings.Value= dt;         warnings.TypeName = "dbo.udt_Warnings";          entities.ExecuteStoredProcedure("usp_RaiseWarnings_rs", userId, warnings, caseId);     } }  public static class ObjectContextExt {     public static void ExecuteStoredProcedure(this ObjectContext context, string storedProcName, params object[] parameters)     {         string command = "EXEC " + storedProcName + " @caseid, @userid, @warnings";          context.ExecuteStoreCommand(command, parameters);     } }   and the stored procedure looks like this:
ALTER PROCEDURE [dbo].[usp_RaiseWarnings_rs]     (@CaseID int,       @UserID uniqueidentifier = '846454D9-DE72-4EF4-ABE2-16EC3710EA0F', --Admin      @Warnings dbo.udt_Warnings READONLY ) AS   and the user-defined table looks like this:
CREATE TYPE [dbo].[udt_Warnings] AS TABLE(     [WarningCode] [nvarchar](5) NULL,     [StatusID] [int] NULL,     [DecisionID] [int] NULL,     [Criticality] [int] NULL DEFAULT ((0)) )   Constraints I found include:
ExecuteStoreCommand have to be in order with the parameters in your stored procedureIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With