2008-10-23 2 views
17

Я пытаюсь заполнить DataTable, чтобы построить LocalReport, используя следующее:
.NET DataTable пропускает строки на Load (DataReader)

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 (в противном случае она только считывает последнюю). Может ли кто-нибудь объяснить, почему это происходит и как оно может быть исправлено?

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

+2

Mod + 1 потому что я программировал .NET и ADO.NET каждый день с момента первых попыток, и я никогда не знал, что могу просто вызвать dt.Load() без DataAdapter. Вздох. – 2008-10-27 01:16:38

+1

Аналогичная ситуация здесь, Дейв. Я узнал об этом всего около месяца назад. – 2008-10-27 19:55:31

+0

Сегодня я опубликовал дублированный вопрос (https://stackoverflow.com/questions/28676382/datatable-load-shows-less-rows-than-source-datareader), который в конечном итоге был разрешен путем переноса запроса. Я хочу подчеркнуть, что это ** только ** происходит на MYSQL. Это не происходит на SQLSERVER.I думаю, что проблема не должна быть вызвана компонентом DataTable, а скорее может быть ошибкой в ​​Mysql-коннекторе. Есть предположения? – 2015-02-23 17:15:35

ответ

2

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

+0

Я испытываю это. У меня уже есть заказ BY – Rhyous 2013-09-25 18:20:23

1

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

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

Вы пробовали разные способы поведения читателей? MSDN Docs

+0

Да, я пытался запустить запросы в клиенте MySQL. Единственное различие между ними заключается в том, что у него ORDER BY Invoice.ID, а у другого нет, оба возвращают две строки в том же порядке. Теперь я собираюсь проверить SqlDataAdapter. – Tom 2008-10-23 11:55:55

+0

Любая удача? Вы случайно не имеете TOP в запросе? – StingyJack 2008-10-24 18:34:04

+1

Использование SqlDataAdapter работало для меня. – Rhyous 2013-09-25 20:33:32

0

Не знаете, почему вам не хватает строки в 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)) 

Любопытно узнать, все ли это происходит.

0

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

+0

Выполнение изменений не производится. – Tom 2008-11-17 14:18:19

0

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

какой a bizzareeee .....

3

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

5

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

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

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

3

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

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

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

2

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

dr.Read() 

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

0

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

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

Таким образом, вместо

SELECT a 
    , b 
FROM table 

Я использовал

SELECT a as gurgleurp 
    , b 
FROM table 

, и она работала.

2

Пошел через эту проблему сегодня.

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

Например:

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

Странно ....

0

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

0

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

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

    if(dataset.hasrows) - Missing row appears.