Как узнать, когда прекратить заполнение OracleDataAdapter - PullRequest
4 голосов
/ 07 июля 2010

Я использую OPD.NET dll в проекте, который обращается к оракулу.

Пользователи могут ввести любой SQL-запрос в текстовое поле, которое затем будет выполнено для БД.Я пытался использовать OracleDataAdapter для заполнения набора данных набором результатов, но я хочу иметь возможность возвращать набор результатов поэтапно (для больших запросов select).

Пример моей проблемы:.

Если запрос на выборку возвращает 13 строк данных, приведенный ниже фрагмент кода будет выполняться без проблем до тех пор, пока не будет вызван oda.Fill в четвертый раз (начальная строка 15, которая не существует), я полагаю, потому что онвызывает читателя, который закрыл или что-то подобное.

Затем будет выдано исключение System.InvalidOperationException с сообщением - операция недопустима из-за текущего состояния объекта.

Как узнать, сколько строк в общей сложности выполнит командав конечном итоге содержать (чтобы я не встретил исключение)?

OracleDataAdapter oda = new OracleDataAdapter(oracleCommand);
oda.Requery = false;

var dts = new DataTable[] { dt };
DataTable dt = new DataTable();

oda.Fill(0, 5, dts);
var a = dts[0].Rows.Count;
oda.Fill(a, 5, dts);
var b = dts[0].Rows.Count;
oda.Fill(b, 5, dts);
var c = dts[0].Rows.Count;
oda.Fill(c, 5, dts);
var d = dts[0].Rows.Count;

Примечание. Я для краткости опускаю объекты подключения и команды оракула. ​​

РЕДАКТИРОВАТЬ 1:просто подумал, что мог бы просто обернуть введенный пользователем SQL в другой запрос и выполнить его ... ВЫБЕРИТЕ СЧЕТЧИК (*) ОТ (здесь начальный запрос ...), но это не совсем чистое решение, инаверняка есть метод где-то, что я не видел?

Заранее спасибо.

Ответы [ 3 ]

1 голос
/ 07 июля 2010

Для просмотра страниц в Oracle см .: http://www.oracle.com/technology/oramag/oracle/06-sep/o56asktom.html

Невозможно узнать количество наборов записей без выполнения отдельного запроса count (*).Это по замыслу.DataReader и DataAdapter предназначены только для пересылки и только для чтения.

Если важна эффективность (т. Е. Большие наборы записей), следует разрешить пейджингу выполнять базу данных, а не запрашивать OracleDataAdapterвыполнить полный запрос.Представьте, что Google заполнил DataTable всеми результатами более 1 млн. Для каждого пользовательского поиска !!Следующая статья решает эту проблему, хотя примеры приведены в sql:

http://www.asp.net/data-access/tutorials/efficiently-paging-through-large-amounts-of-data-cs

Я пересмотрел мой пример ниже, чтобы разрешить разбиение на страницы для любого запроса SQL.Процедура вызова отвечает за отслеживание текущей страницы пользователя и размера страницы.Если результирующий набор меньше запрошенного размера страницы, страниц больше нет.

Конечно, запуск пользовательского sql из пользовательского ввода представляет огромную угрозу безопасности.Но этот вопрос не был под рукой.

Удачи!- Бретт

DataTable GetReport(string sql, int pageIndex, int pageSize)
{
    DataTable table = new DataTable();

    int rowStart = pageIndex * pageSize + 1;
    int rowEnd = (pageIndex + 1) * pageSize;

    string qry = string.Format(
@"select * 
from (select rownum ""ROWNUM"", a.*
    from ({0}) a
    where rownum <= :rowEnd)
where ""ROWNUM"" >= :rowStart
", sql);
    try
    {
        using (OracleConnection conn = new OracleConnection(_connStr))
        {
            OracleCommand cmd = new OracleCommand(qry, conn);
            cmd.Parameters.Add(":rowEnd", OracleDbType.Int32).Value = rowEnd;
            cmd.Parameters.Add(":rowStart", OracleDbType.Int32).Value = rowStart;
            cmd.CommandType = CommandType.Text;
            conn.Open();
            OracleDataAdapter oda = new OracleDataAdapter(cmd);
            oda.Fill(table);
        }
    }
    catch (Exception)
    {
        throw;
    }
    return table;        
}
0 голосов
/ 08 июля 2010

Чтобы получить контроль над Fill DataTable Loop, вам необходим собственный цикл.

Затем создайте свою собственную функцию для заполнения DataTable с помощью OracleDataReader.

Чтобы получить информацию о столбцах, вы можете использовать dataReader.GetSchemaTable

Для заполнения таблицы:

  MyTable.BeginLoadData 
  Dim Values(mySchema.rows.count-1)
  Do while myReader.read
    MyReader.GetValues(Values)
    MyTable.Rows.add(Values)

    'Include here your control over load Count 
  Loop
  MyTable.EndLoadData
0 голосов
/ 07 июля 2010

Вы можете добавить Analytic COUNT к вашему запросу:

SELECT foo, bar, COUNT(*) OVER () TheCount WHERE ...;

Таким образом, счетчик всего запроса возвращается с каждой строкой в ​​TheCount, и вы можете настроить цикл таким образом, чтобы он соответствующим образом завершался.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...