Reputation: 31
I'm using the latest EF.core version (5.0.7) and attempting to retrieve entities via stored procedure. Tried the following:
//attemp 1
res = _context.Entity.FromSqlRaw($"exec dbo.ProcedureName");
//attemp 2
res = _context.Entity.FromSqlRaw("exec ProcedureName", new SqlParameter("@ParamName", paramValue));
//attemp 3
res = _context.Entity.FromSqlRaw($"exec ProcedureName {paramValue}");
//attemp 4
res = _context.Entity.FromSqlInterpolated($"exec ProcedureName @ParamName = {paramValue}");
//attemp 5
res = _context.Entity.FromSqlInterpolated($"exec ProcedureName {paramValue}");
All of the examples and without the "exec", parameter name with and without "@" and procedure name with and without leading "dbo" I keep getting the error "System.InvalidOperationException: FromSqlRaw or FromSqlInterpolated was called with non-compostable SQL and with a query composing over it. Consider calling AsEnumerable after the FromSqlRaw or FromSqlInterpolated method to perform the composition on the client-side." what am I doing wrong?
P.S.
Client-side composition is not an option.
The procedure works fine in SSMS.
In another thread This was claimed to be an issue resolved by EF5.0, but it clearly isn't.
Upvotes: 3
Views: 502
Reputation: 3704
Entity Framework throws the exception preventing server-side composition unless the query starts with "SELECT".
if (char.ToLowerInvariant(c) == 's'
&& char.ToLowerInvariant(NextChar()) == 'e'
&& char.ToLowerInvariant(NextChar()) == 'l'
&& char.ToLowerInvariant(NextChar()) == 'e'
&& char.ToLowerInvariant(NextChar()) == 'c'
&& char.ToLowerInvariant(NextChar()) == 't')
{
var (c1, c2) = (NextChar(), NextChar());
if (char.IsWhiteSpace(c1)
|| c1 == '-' && c2 == '-'
|| c1 == '/' && c2 == '*')
{
return;
}
}
throw new InvalidOperationException(RelationalStrings.FromSqlNonComposable);
You specifically mention "Client-side composition is not an option" but as Ivan Stoev commented, SQL Server does not support composition over stored procedures. The recommendation to re-write as a table-valued function may be possible if it can be done without side effects that modify the database state.
There's a whole pile of issues related to FromSql and mapping, some of which reference composition. I believe this one indicates that EF5.0 only resolved the 'non-composable' exception for root table-per-hierarchy entities.
Upvotes: 0
Reputation: 71119
In order to use FromSqlRaw
, you need to let it do the interpolation, it will convert it to parameters. Do not do it yourself.
res = _context.Entity
.FromSqlRaw("exec ProcedureName @ParamName = {paramValue}", paramvalue)
.AsEnumerable();
Note the lack of the $
. You also need to add AsEnumerable
to prevent it from trying to compose it.
Upvotes: 2