.NET DataTable は Load(DataReader) で行をスキップします
-
04-07-2019 - |
質問
次を使用して、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);
ある時点で、レポートが不完全で、レコードが 1 つ欠けていることに気づきました。クエリが正確に 2 行を返すように、いくつかの条件を変更しました。 驚き:レポートには 2 行ではなく 1 行のみが表示されます。問題がどこにあるのかを見つけるためにデバッグしようとしましたが、次の点で行き詰まってしまいました。
dt.Load(cmd.ExecuteReader());
それに気づいたとき、 DataReader
2 つのレコードが含まれていますが、 DataTable
1 つだけ含まれています。偶然、追加してしまいました ORDER BY
クエリに句を追加したところ、今度はレポートが正しく表示されたことがわかりました。
どうやら、DataReader には 2 つの行が含まれていますが、SQL クエリ文字列に ORDER BY
(そうでない場合は、最後のもののみを読み取ります)。なぜこれが起こっているのか、そしてどのように修正できるのかを説明できる人はいますか?
編集:最初に質問を投稿したとき、最初の行がスキップされていると言いました。後で、実際には最後の行だけを読み取っていることに気づき、それに応じてテキストを編集しました(当時、すべてのレコードは2行にグループ化されており、実際には最後の行のみが表示されているのに最初の行がスキップされているように見えました)。これは、MySQL から返される行を区別するための一意の識別子がなかったことが原因である可能性があるため、 ORDER BY
ステートメントにより、行ごとに一意の識別子が作成されました。
これは単なる理論であり、それを裏付けるものは何もありませんが、すべてのテストでは同じ結果が得られるようです。
解決
同じ問題がありました。私はあなたのブログからヒントを得て、クエリで返されるすべてのレコードの一意のキーを一緒に形成できるように、クエリにORDER BY句を設定しました。問題を解決しました。ちょっと変です。
他のヒント
質問は数年前のものですが、上記の回避策を除いて、きちんとした答えは見つかりませんでした。
かなりいじくり回した後、DataTable.Loadメソッドは基本データの主キー列を予期していることがわかりました。ドキュメンテーションを注意深く読むと、これは明白になりますが、明示的には明記されていません。
" id"という名前の列がある場合それはそれを使用しているようです(私のためにそれを修正しました)。それ以外の場合、一意であるかどうかに関係なく、最初の列を使用するように見え、その列で読み取られているのと同じ値で行を上書きします。 " id"という名前の列がない場合最初の列が一意ではない場合、データリーダーをロードする前に、データテーブルの主キー列を明示的に設定することをお勧めします。
誰かがcanceriensと同様の問題を抱えている場合、If DataReader.HasRows
の代わりにIf DataReader.Read
...を使用して呼び出し前に存在を確認していました dt.load(DataReader)
Doh!
同じ問題がありました。これは、すべての行の主キーが同じだからです。これはおそらく結果のキーイングに使用されているものなので、同じ行を何度も何度も上書きしているだけです。
Datatables.Loadはfillメソッドを指し示し、その動作を理解します。このページでは、主キーを認識していると述べています。主キーは1回しか使用できず、行のキーとして使用されるため...
" Fill操作は、行をDataSetの宛先DataTableオブジェクトに追加し、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プロファイラーから実行されている実際のクエリを取得して実行してみてください。それはあなたが期待したものではないかもしれません。
SqlDataAdapter.Fill(dataTable)を使用しても同じ結果が得られますか?
リーダーでさまざまなコマンド動作を試しましたか? MSDNドキュメント
これは古い質問であることは知っていますが、私にとっては、アクセスデータベースにクエリを実行し、クエリから1行が欠落していることに気付いたとき、次のように変更することでした:-
if(dataset.read()) - Misses a row.
if(dataset.hasrows) - Missing row appears.
データテーブルの行が欠落している理由がわかりません。リーダーを閉じる必要がある可能性はありますか?いずれにせよ、ここに私が通常レポートをロードする方法があり、毎回動作します...
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 件しか表示されません。最初の行をスキップし、データリーダーにレコードが 1 つしかない場合は何も表示されません。
何という奇怪な……
dt.Load(cmd.ExecuteReader())
呼び出しの後に dt.AcceptChanges()
を呼び出して、それが役立つかどうかを確認しましたか?
これは古い質問であることは知っていますが、同じ問題が発生していたため、ここで説明した回避策はどれも役に立ちませんでした。
私の場合、 PrimaryKey
として使用されている列のエイリアスを使用して問題を解決しました。
だから、代わりに
SELECT a
, b
FROM table
使用しました
SELECT a as gurgleurp
, b
FROM table
それは機能しました。
同じ問題が発生しました。dataReader.Read()をまったく使用しません。次の行へのポインタを取得します。代わりに、直接datatable.load(dataReader)を使用します。