I need to build a raw SQL query and I am using the new EF Core 8. But when it executes the query, it seems that the parameters are not getting replaced.
private static FormattableString GetCardsBaseQuery(CardListFilter filter)
{
var rows = filter!.RowsPerPage ?? 10;
int offset = filter.Page ?? 1 - 1;
offset = offset < 0 ?
rows :
rows * offset;
var orderByParameter = new SqlParameter { ParameterName = "orderBy", SqlDbType = SqlDbType.NVarChar, Value = filter.SortBy };
var orderByDirectionParameter = new SqlParameter { ParameterName = "orderDirection", SqlDbType = SqlDbType.NVarChar, Value = filter.SortDirection };
var offsetParametar = new SqlParameter { ParameterName = "offset", SqlDbType = SqlDbType.Int, Value = offset };
var rawParameter = new SqlParameter { ParameterName = "rows", SqlDbType = SqlDbType.Int, Value = rows };
//! if you modify this query then you should change the CardListModel(reader) constructor as well
var query = FormattableStringFactory.Create(@"
SELECT
c.BatchId,
c.LuckyId,
c.RefId,
SUBSTRING(c.RefId, 6, 16) as [RawRefId],
(c.FirstName + ' ' + c.LastName) as [Name],
c.Email,
c.MobileNumber,
c.HasMarketingPermisson,
c.Status,
c.PlayedAt,
c.BigPrize,
c.DipPrize,
c.DrawPrize,
c.BigPrizePaymentStatus,
c.BonusDrawStatus
FROM
[Card] c
ORDER BY {0} {1}
OFFSET {2} ROWS
FETCH NEXT {3} ROWS ONLY", orderByParameter.Value, orderByDirectionParameter.Value, offsetParametar.Value, rawParameter.Value);
return query;
}
public async Task<CardListModel> GetCardsByFilterAsync(CardListFilter filter)
{
var basequery = GetCardsBaseQuery(filter);
var queryable = context.Database.SqlQuery<CardListModel>(basequery);
var result = await queryable.ToListAsync();
return result ;
}
When I print the generated and executed query on console, I see the following error:
*error : Failed executing DbCommand (26ms) [Parameters=[p0='?' (Size = 4000), p1='?' (DbType = Int32), p2='?' (DbType = Int32), p3='?' (DbType = Int32)], CommandType='Text', CommandTimeout='300']
SELECT
c.BatchId,
c.LuckyId,
c.GilRefId,
SUBSTRING(c.GilRefId, 6, 16) as [RawGilRefId],
(c.FirstName + ' ' + c.LastName) as [Name],
c.Email,
c.MobileNumber,
c.HasMarketingPermisson,
c.Status,
c.PlayedAt,
c.BigPrize,
c.LuckyDipPrize,
c.BonusDrawPrize,
c.BigPrizePaymentStatus,
c.BonusDrawStatus
FROM
[Card] c
ORDER BY @p0 @p1
OFFSET @p2 ROWS
FETCH NEXT @p3 ROWS ONLY
fail: 02/03/2024 09:39:23.574 RelationalEventId.CommandError[20102] (Microsoft.EntityFrameworkCore.Database.Command)*
When I debug the code, I can see that the basequery variable got the params right with the right indexes, the values are ok, and if I copy the query everything is fine, it executes, but when it executes the param values are missing.
Thanks
ASC/DESCand column name forORDER BYcan't be parameterized. You need to validate them beforehand (for direction it is easy - basically it has only 3 possible values - ascending, descending and "null or empty") and inlining it (also maybeorderBywill need the same treatment too):Also creating parameter variables in the way you use them is not needed, you can pass the
filtervalues directly (i.e.filter.SortByetc.)