efcore: Raw store access: Support execution of SQL that returns results but is not composable on the store, e.g. stored procedures

We should provide a simple mechanism to execute queries/commands such as regular stored procedures that contain a SELECT statement. What FromSql() does won’t work for those because you cannot used them as sub queries.

A few things we could use:

  1. Provide an API akin FromSql() but switch composition to in-memory if subsequent LINQ operators are applied. Same warning and kill switch for query evaluation we have talked about having for other queries would apply to these.
  2. Provide a completely separate API pattern that is meant for non-composable results and even not return IEnumerable<T> but a new type that implements GetEnumerator() and AsEnumerable()
  3. Stick the stored procedure results into a table-valued variable and then keep composing as normal. This would move processing to the server and make composition more seamless but would most likely not make it any more efficient than option (1).
  4. Recognize the token “EXEC” in FromSql() (which is pretty standard although no longer required) for SQL Server as an indication that what follows is a non-composable stored procedure and that needs to go through a different execution mode (e.g. the one described in (1) or the one described in (3)).

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 17 (11 by maintainers)

Most upvoted comments

I have made this to call stored procedure and map the DataReader to a specified model. I hope it helps.

We don’t currently have support for named parameters in FromSql and ExecuteSqlCommand. There are plans to support other patterns in the future (i.e. SqlParameter, DbParameter, anonymous types), but for now you should be able to use the somewhat clunky pattern that we use in FromSqlSprocQuerySqlServerTest:

var userType = dbContext.Set().FromSql("dbo.SomeSproc @Id = {0}, @Name = {1}", 45, "Ada");

How to pass “named” parameters in FromSql()?

Example:

object[] sqlParams = { new SqlParameter(“@Id”, 45), new SqlParameter(“@Name”, “Ada”) };

var UserType = dbcontext.Set<UserType>().FromSql(“dbo.SomeSproc”, sqlParams)

If SqlParameter is not supported then something like this would suffice:

var parameterDictionary = new Dictionary<string, object> { {“@Id”, 45}, {“@Name”, “Ada”} };