.NET DataTable пропускает строки При загрузке(DataReader)

Я пытаюсь заполнить DataTable, чтобы построить LocalReport, используя следующее:

MySqlCommand cmd = new MySqlCommand();
cmd.Connection = new MySqlConnection(Properties.Settings.Default.dbConnectionString);
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT ... LEFT JOIN ... WHERE ..."; /* query snipped */

// prepare data
dataTable.Clear();
cn.Open();
// fill datatable
dt.Load(cmd.ExecuteReader());
// fill report
rds = new ReportDataSource("InvoicesDataSet_InvoiceTable",dt);
reportViewerLocal.LocalReport.DataSources.Clear();
reportViewerLocal.LocalReport.DataSources.Add(rds);
сюрприз отчет показывает только одну строку вместо двух. Я попытался отладить его, чтобы найти, где проблема, и я застрял в
 dt.Load(cmd.ExecuteReader());

когда я заметил, что DataReader содержит две записи, но DataTable содержит только один. Случайно, я добавил ORDER BY предложение к запросу и заметил, что на этот раз отчет показал правильно.

По-видимому, DataReader содержит две строки, но DataTable считывает только обе из них, если строка запроса SQL содержит ORDER BY (в противном случае он читает только последний). Может кто-нибудь объяснить, почему это происходит и как это можно исправить?

Edit: Когда я впервые опубликовал вопрос, я сказал, что он пропускает первую строку; позже я понял, что на самом деле он читает только последнюю строку, и я отредактировал текст соответственно (в то время все записи были сгруппированы в две строки, и казалось, что он пропустил первый, когда он фактически показал только последний). Это может быть вызвано тем, что у него не было уникального идентификатора, по которому можно различать строки, возвращаемые MySQL, поэтому добавление ORDER BY оператор заставил его создать уникальный идентификатор для каждого ряд.
Это всего лишь теория, и у меня нет ничего, чтобы ее поддержать, но все мои тесты, похоже, приводят к одному и тому же результату.

13 ответов


У меня была такая же проблема. Я взял подсказку из вашего блога и разместил предложение ORDER BY в запросе, чтобы они могли вместе сформировать уникальный ключ для всех записей, возвращаемых запросом. Это решило проблему. Немного странно.


вопрос несколько лет, но я не нашел достойного ответа, кроме упомянутой выше решение.

поиграв немного, я обнаружил, что DataTable.Метод Load ожидает столбец первичного ключа в базовых данных. Если вы внимательно прочтете документацию, это станет очевидным, хотя и не указано очень явно.

Если у вас есть столбец с именем "id", он, похоже, использует это (что исправило его для меня). В противном случае это просто кажется используйте первый столбец, уникальный он или нет, и перезаписывайте строки с тем же значением в этом столбце, что и при чтении. Если у вас нет столбца с именем "id", и ваш первый столбец не уникален, я бы предложил попытаться явно установить столбец(ы) первичного ключа datatable перед загрузкой datareader.


на всякий случай, если у кого-то есть аналогичная проблема, как canceriens, я использовал If DataReader.Read ... вместо If DataReader.HasRows чтобы проверить существование перед вызовом dt.load(DataReader) Doh!


была та же проблема. Это потому, что первичный ключ во всех строках один и тот же. Вероятно, это то, что используется для ключа результатов, и поэтому он просто перезаписывает одну и ту же строку снова и снова.

объекты DataTable.Load указывает на метод fill, чтобы понять, как он работает. На этой странице указано, что это первичный ключ. Поскольку первичные ключи могут возникать только один раз и используются в качестве ключей для строки ...

" операция заполнения затем добавляет строки в назначение объектов DataTable в DataSet, создание объектов DataTable, если они еще не существуют. При создании объектов DataTable операция Fill обычно создает только метаданные имени столбца. Однако если свойству MissingSchemaAction присвоено значение AddWithKey, также создаются соответствующие первичные ключи и ограничения."(http://msdn.microsoft.com/en-us/library/zxkb3c3d.aspx)


столкнулся с этой проблемой сегодня.

ничего в этом потоке не исправлено, к сожалению, но затем я завернул свой SQL-запрос в другой оператор SELECT, и он работает!

например:

SELECT * FROM (
    SELECT ..... < YOUR NORMAL SQL STATEMENT HERE />
) allrecords

странно....


Не используйте

dr.Read()

потому что он перемещает указатель на следующую строку. Удалите эту линию, надеюсь, она будет работать.


можете ли вы захватить фактический запрос, который выполняется из SQL profiler и попробовать запустить его? Возможно, это не то, что вы ожидали.

вы получаете тот же результат при использовании SqlDataAdapter.Заполнить (dataTable)?

вы пробовали различные командные поведения на читателе? документы MSDN


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

        Dim deals As New DealsProvider()
        Dim adapter As New ReportingDataTableAdapters.ReportDealsAdapter
        Dim report As ReportingData.ReportDealsDataTable = deals.GetActiveDealsReport()
        rptReports.LocalReport.DataSources.Add(New ReportDataSource("ActiveDeals_Data", report))

любопытно посмотреть, если это все еще происходит.


в моем случае ни ORDER BY, ни dt.AcceptChanges () работает. Я не знаю, почему это проблема. У меня есть 50 записей в базе данных, но он показывает только 49 в datatable. пропуск первой строки, и если в datareader есть только одна запись, она вообще ничего не показывает.

какой bizzareeee.....


вы пробовали позвонить dt.AcceptChanges() после dt.Load(cmd.ExecuteReader()) позвоните, чтобы узнать, помогает ли это?


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

В моем случае, используя псевдоним на сайте, который используется как PrimaryKey решается вопрос.

Итак, вместо

SELECT a
     , b
FROM table

Я

SELECT a as gurgleurp
     , b
FROM table

и это сработало.


У меня была та же проблема.. не используйте dataReader.Читать() вообще.. он будет принимать указатель на следующую строку. Вместо этого используйте непосредственно datatable.загрузить (dataReader).


Я знаю, что это старый вопрос, но для меня думаю, что работал во время запроса базы данных access и заметив, что отсутствует 1 строка из запроса, должен был изменить следующее: -

    if(dataset.read())  - Misses a row.

    if(dataset.hasrows) - Missing row appears.