Разбиение на страницы запросов с использованием DataAdapters - PullRequest
0 голосов
/ 14 января 2019

Я пытаюсь разбить свои запросы на страницы, используя методы расширения 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 построено на параметризованных запросах (без конкатенации строк)

...