2010-04-10 2 views
2

Я хочу показать подробную информацию о состоянии пользователя при выполнении длительных операций с базой данных. В частности, при вставке/обновлении данных, которые могут быть порядка сотен КБ или МБ.Как лучше показать информацию о ходе работы при использовании ADO.NET?

В настоящее время я использую in-memory DataTables и DataRows, которые затем синхронизируются с базой данных через вызовы TableAdapter.Update. Это отлично работает и денди, но единственный вызов оставляет мало возможностей для сбора информации о ходе работы, чтобы показать пользователю. Я понятия не имею, сколько данных проходит через сеть для удаленной БД или ее прогресса. В принципе, все, что я знаю, - это когда Update возвращается и считается полным (запрет на любые ошибки или исключения). Но это означает, что все, что я могу показать, это 0%, а затем пауза, а затем 100%.

Я могу подсчитать количество строк, даже до тех пор, пока не набросано, сколько из них действительно модифицировано или добавлено, и я даже мог бы вычислить на DataRow его предполагаемый размер на основе типа данных каждого столбца, используя sizeof для типов значений как int и проверяя длину для таких вещей, как строки или байтовые массивы. При этом я мог бы, вероятно, определить, до обновления, приблизительный общий размер передачи, но я все равно застрял без какой-либо информации о ходе, как только Update вызывается в TableAdapter.

Я застрял только с помощью неопределенного индикатора хода или мыши, ожидающего курсора? Нужно ли мне радикально изменить наш уровень доступа к данным, чтобы иметь возможность подключаться к такой информации? Даже если я не могу довести его до того, что передал точный КБ (например, индикатор выполнения загрузки файла веб-браузера), могу ли я, по крайней мере, узнать, когда заканчивается каждый DataRow/DataTable или что-то в этом роде?

Как вы можете лучше всего показывать информацию о прогрессе с помощью ADO.NET?

ответ

1

Существует часть решения для части SELECT, которая должна сначала выполнить запрос COUNT, чтобы получить количество строк, которые вы ожидаете получить. Это практично, только если запрос COUNT может вернуть результат очень быстро (т. Е. В доли секунды) - с другой стороны, если требуется несколько секунд для запуска, то само выполнение запроса (в отличие от перечисления результатов) может занимают больше времени, чем передача данных, и в этом случае не стоит вообще пытаться показывать дискретный индикатор выполнения.

Что касается UPDATE и INSERT - нет, на самом деле нет простого решения, особенно с помощью TableAdapters. Если у вас есть огромное количество данных для отправки, вы можете захотеть использовать класс SqlBulkCopy для загрузки в промежуточную таблицу, а затем выполнить фактическое обновление на сервере. Этот класс предлагает свойство NotifyAfter вместе с событием SqlRowsCopied, которое может дать вам разумное приближение текущего прогресса (вы уже знаете общее количество строк в этом случае, так как они находятся в памяти).

Это, конечно, потребует значительных изменений от текущей реализации TableAdapter, но типизированная система набора данных в .NET действительно не была предназначена для обработки наборов записей такого размера по сравнению с подключением к локальной сети.

Я думаю, что большинство людей просто предпочли бы использовать индикатор выполнения шага. Пользователи ожидают этого в наши дни; даже если бы вы могли точно предсказать количество строк и скорость передачи данных, вы все равно не знаете, сколько времени потребуется на выполнение запроса, особенно если сервер находится под большой нагрузкой, и, возможно, хуже обеспечить bad estimates чем никакие оценки.

Если существует реальная вероятность того, что сам запрос (или обновление) займет много времени для запуска на сервере, не считая времени на загрузку/загрузку записей, тогда я бы определенно использовал индикатор выполнения marquee , Иначе ... удачи.

+0

ли SqlBulkCopy попытаться вставить все строки как новые строки? Под этим я подразумеваю, что если DataTable, переданный ему при вызове WriteToServer, имеет несколько строк, которые являются «RowState == Modified», то обновляет ли эти строки или вставляет копии с новыми PK? Что делать, если KeepIdentity включен? Если он пытается вставить, и ПК одинаковы, я полагаю, что это вызовет исключение SqlException. Возможно, это заслуживает отдельного вопроса. Документы MSDN не были конкретными ... –

+0

Nevermind. Когда MSDN docs терпят неудачу, блоги MSDN на помощь. http://blogs.msdn.com/irenak/archive/2006/02/10/529553.aspx –

+0

@Yadyn: 'SqlBulkCopy' завершает операцию массовой вставки, которая не обновляется, что является причиной, по которой вам необходимо использовать промежуточную Таблица. В общем, вам вряд ли удастся заставить «DataSet» и связанные с ними классы работать с любым из других классов данных в рамках - вам, вероятно, придется начать отходить от них, поскольку они основанный на концепции загрузки всего набора записей в память, а не потоковой передачи их из TDS. – Aaronaught

0

As Aaronaught said - SqlBulkCopy с NotifyAfter должен работать (он работает для меня, хотя).

Я не думаю, что это будет «существенное изменение» для текущей реализации DAL ...

Смежные вопросы