Я не использовал SqlBulkCopy, но, как правило, DataReaders обычно предлагает лучшую производительность.
DataReader может быть обработан, пока базовый запрос все еще возвращает записи (поэтому вам не нужно ждать завершения запроса, прежде чем вы сможете начать обработку данных). DataReader вернет данные, как только они станут доступными, и я верю, что по умолчанию будет сохраняться только активная запись в памяти (а не полный набор результатов), что сокращает использование памяти.
DataAdapter загружает полный набор результатов в DataTable / DataSet, который будет иметь более высокие издержки из-за того, как информация хранится в памяти, и дополнительного связанного состояния (например, состояния строки и т. Д.).
Если я только читаю данные, я всегда буду использовать DataReader поверх DataAdapter ... кто-нибудь, пожалуйста, исправьте меня, если я ошибаюсь в какой-либо точке?
Несмотря на это, SqlBulkCopy, похоже, выполняет итерацию только по записям и не использует DataTable для каких-либо оптимизаций (согласно Reflector), поэтому я думаю, что DataReader - ваш лучший выбор.