Я пытаюсь разбить свои запросы на страницы, используя методы расширения Data Adapter.
Вот что я реализовал:
public static PagingInformation ExecutePagingInformation(
this IDbCommand dbCommand, int pageIndex, int pageSize,
CancellationToken cancellationToken = default)
{
string oldCommandText = dbCommand.CommandText;
dbCommand.CommandText = $"SELECT COUNT(*) FROM ({dbCommand.CommandText}) Q";
var totalCount = Convert.ToInt32(dbCommand.ExecuteScalar());
dbCommand.CommandText = oldCommandText;
return new PagingInformation(pageIndex, pageSize, 0, totalCount);
}
public static DbDataReader ExecutePagedReader(
this IDbCommand dbCommand, int pageIndex, int pageSize,
out PagingInformation pageInformation)
{
if (dbCommand.CommandType != CommandType.Text)
throw new InvalidOperationException("Only CommandType.Text is supported.");
DbDataReader reader;
if (dbCommand is OracleCommand oracleCommand)
{
pageInformation = dbCommand.ExecutePagingInformation(pageIndex, pageSize); //this is implemented by myself
reader = oracleCommand.ExecutePageReader(CommandBehavior.Default, pageIndex * pageSize, pageSize); //this is native method
}
else
{
throw new NotSupportedException();
}
return reader;
}
тогда я использую их как
using (var reader = cmd.ExecutePagedReader(pageIndex, pageSize, out pagingInformation))
{
while (await reader.ReadAsync(cancellationToken))
{
result.Add(reader[0].ToString());
}
}
проблема в $"SELECT COUNT(*) FROM ({dbCommand.CommandText}) Q";
части, которая подлежит SQL-инъекции . Я рассматриваю возможность создания другого экземпляра SQLCommand и использования параметризованного запроса, однако я не уверен, что параметризованный запрос может создать мой внутренний запрос, не экранируя обычный SQL (думаю, этот подход не будет работать)
Devart DotConnect For Oracle имеет OracleDataReader
, который разбивает результаты на страницы с помощью ExecutePageReader
. Я декомпилировал его, и, насколько я понимаю, они используют StringBuilder для генерации запроса, который поддерживает разбиение на страницы. Тем не менее, код запутан, и я не мог найти решение.
Редактировать:
$"SELECT COUNT(*) FROM ({dbCommand.CommandText}) Q";
dbCommand.CommandText
построено на параметризованных запросах (без конкатенации строк)