Reputation: 3541
I have a stored procedure with an input that defines the columns that are returned.
How can I iterate through the result?
I have tried solutions similar to this:
var selectColsParam = new System.Data.SqlClient.SqlParameter()
{
ParameterName = "@SelectCols",
Value = "Person.FirstName",
};
string sql = string.Format("dbo.DynamicResultSP {0} ", selectColsParam.ParameterName);
var result = db.Database.SqlQuery<List<dynamic>>(sql, selectColsParam);
At best, 'result' contains the correct number of rows which I can iterate through, but the 'row' itself is simply an object I can't seem to do anything with.
I don't need to know the column names but need to be able to iterate through the fields.
I know having a stored procedure that returns different columns depending on input is not considered good design, however, this is what I have to work with and so changing the SP is not an option.
Any help is appreciated
Upvotes: 2
Views: 6053
Reputation: 233
I ran into the same problem today, and had to resort back to SqlCommand
rather than use the object context directly.
// Retrieve the connection from the object context
var entityConnection = this.ObjectContext.GetConnection() as EntityConnection;
var dbConnection = entityConnection.StoreConnection as SqlConnection;
// Create the command and associated parameters (dynamically passed in perhaps)
var command = new SqlCommand("dbo.DynamicResultSP");
command.Parameters.AddWithValue("@SelectCols", "Person.FirstName");
////command.Parameters.AddWithValue("@AnotherParameter", "Parameter.SecondValue");
////command.Parameters.AddWithValue("@AThirdParameter", "YetAnotherValue");
dbConnection.Open();
using (var reader = command.ExecuteReader())
{
// Get the column names
columnNames = new string[reader.FieldCount];
for (int i = 0; i < reader.FieldCount; i++)
{
columnNames[i] = reader.GetName(i);
}
// Get the actual results
while (reader.Read())
{
var result = new string[reader.FieldCount];
for (int i = 0; i < reader.FieldCount; i++)
{
result[i] = reader[i].ToString();
}
results.Add(result);
}
}
dbConnection.Close();
Now you should have access to both the names of the fields and the results.
Whilst it's not the prettiest solution, it gets the job done. Suggestions welcome.
Upvotes: 2
Reputation: 532435
I ran into a similar issue when testing JsonResults. You might be interested in a little extension I wrote that allows you to convert an object
to a dynamic which would allow you to hook into the runtime dynamic binding on each object.
It might look like:
var result = db.Database.SqlQuery<List<object>>(sql, selectColsParam);
var dynamicResults = result.Select(o => o.AsDynamic()).ToList();
foreach (dynamic item in dynamicResults)
{
// treat as a particular type based on the position in the list
}
It's also possible that you might simply need to convert each element to the proper type based on whatever logic you have to determine that using Convert
or by directly casting.
Upvotes: 0