C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[9]: ArrayListとMDBのやりとり


(過去ログ 127 を表示中)

[トピック内 12 記事 (1 - 12 表示)]  << 0 >>

■75254 / inTopicNo.1)  ArrayListとMDBのやりとり
  
□投稿者/ MP枯渇ウィザード (3回)-(2015/03/09(Mon) 11:42:32)

分類:[.NET 全般] 

Windows7-32Bit
VB2010Formアプリケーション


お世話になります。
今やろうとしていることが、

CSVファイルA群を読み込んで、ArrayListAAに入れる
CSVファイルB群を読み込んで、ArrayListBBに入れる

AAをX.MdbのテーブルAAAに入れる
BBをX.mdbのテーブルBBBに入れる

AAAとBBBで演算した結果をX.mdbのテーブルCCCに入れる

DataGridViewでCCCを表示する

という流れなのですが、

mdbの生成、テーブルの生成まではできたのですが、
ArrayListをテーブルに挿入できません。
ArrayListを使っている場合でも、何かしらのプロパティを引っ張ってきてループ処理になるのでしょうか?
それとも、もうArrayListで構造が出来ているので、何かしらの命令1発で書き込むことができるのでしょうか?
逆にMDBからArrayListに書き込むときも同様なのでしょうか?
宜しく御願い致します。
引用返信 編集キー/
■75255 / inTopicNo.2)  Re[1]: ArrayListとMDBのやりとり
□投稿者/ WebSurfer (519回)-(2015/03/09(Mon) 11:53:29)
No75254 (MP枯渇ウィザード さん) に返信

> ArrayListを使っている場合でも、何かしらのプロパティを引っ張ってきてループ処理になるのでしょうか?

基本的にそうです。ただし「何かしらのプロパティを引っ張って」ではなくて ADO.NET ラ
イブラリを使ったコードを自力で書くことになるはずです。
引用返信 編集キー/
■75256 / inTopicNo.3)  Re[2]: ArrayListとMDBのやりとり
□投稿者/ MP枯渇ウィザード (5回)-(2015/03/09(Mon) 13:27:27)
No75255 (WebSurfer さん) に返信
> ■No75254 (MP枯渇ウィザード さん) に返信
>
>>ArrayListを使っている場合でも、何かしらのプロパティを引っ張ってきてループ処理になるのでしょうか?
>
> 基本的にそうです。ただし「何かしらのプロパティを引っ張って」ではなくて ADO.NET ラ
> イブラリを使ったコードを自力で書くことになるはずです。

御返答ありがとうございます。
やはりそうなりますよね。

Dim cn As New OleDb.OleDbConnection
'コマンド用変数
Dim SQLcm As OleDb.OleDbCommand = cn.CreateCommand
'Accessファイルの格納変数
cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source = " & TargetMDB & ";"
'データベースを開く
cn.Open()

For i = 0 To ReadJdg.Count - 1
Debug.WriteLine(ReadJdg(i))
SQLcm.CommandText = "insert into judge values('" & ReadJdg(i) & "')"
SQLcm.ExecuteNonQuery()
Next
とすると、System.InvalidCastException
演算子 '&' は 文字列 "insert into judge values('" と 型 'String()' に対して定義されていません。
とエラーを吐きます。
単にSQL文作るために文字列連結したいだけなのに・・・
引用返信 編集キー/
■75259 / inTopicNo.4)  Re[3]: ArrayListとMDBのやりとり
□投稿者/ WebSurfer (520回)-(2015/03/09(Mon) 13:50:20)
No75256 (MP枯渇ウィザード さん) に返信
> ■No75255 (WebSurfer さん) に返信
>>■No75254 (MP枯渇ウィザード さん) に返信
>>
> >>ArrayListを使っている場合でも、何かしらのプロパティを引っ張ってきてループ処理になるのでしょうか?
>>
>>基本的にそうです。ただし「何かしらのプロパティを引っ張って」ではなくて ADO.NET ラ
>>イブラリを使ったコードを自力で書くことになるはずです。
>
> 御返答ありがとうございます。
> やはりそうなりますよね。
>
> Dim cn As New OleDb.OleDbConnection
> 'コマンド用変数
> Dim SQLcm As OleDb.OleDbCommand = cn.CreateCommand
> 'Accessファイルの格納変数
> cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
> "Data Source = " & TargetMDB & ";"
> 'データベースを開く
> cn.Open()
>
> For i = 0 To ReadJdg.Count - 1
> Debug.WriteLine(ReadJdg(i))
> SQLcm.CommandText = "insert into judge values('" & ReadJdg(i) & "')"
> SQLcm.ExecuteNonQuery()
> Next
> とすると、System.InvalidCastException
> 演算子 '&' は 文字列 "insert into judge values('" と 型 'String()' に対して定義されていません。
> とエラーを吐きます。
> 単にSQL文作るために文字列連結したいだけなのに・・・

まず、ループで回すものが間違ってます。あと、パラメータ化しましょう。
引用返信 編集キー/
■75261 / inTopicNo.5)  Re[4]: ArrayListとMDBのやりとり
□投稿者/ MP枯渇ウィザード (6回)-(2015/03/09(Mon) 15:52:44)
No75259 (WebSurfer さん) に返信
> ■No75256 (MP枯渇ウィザード さん) に返信
>>■No75255 (WebSurfer さん) に返信
> >>■No75254 (MP枯渇ウィザード さん) に返信
> >>
>>>>ArrayListを使っている場合でも、何かしらのプロパティを引っ張ってきてループ処理になるのでしょうか?
> >>
> >>基本的にそうです。ただし「何かしらのプロパティを引っ張って」ではなくて ADO.NET ラ
> >>イブラリを使ったコードを自力で書くことになるはずです。
>>
>>御返答ありがとうございます。
>>やはりそうなりますよね。
>>
>>        Dim cn As New OleDb.OleDbConnection
>>        'コマンド用変数
>>        Dim SQLcm As OleDb.OleDbCommand = cn.CreateCommand
>>        'Accessファイルの格納変数
>>        cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
>>        "Data Source = " & TargetMDB & ";"
>>        'データベースを開く
>>        cn.Open()
>>
>>        For i = 0 To ReadJdg.Count - 1
>>            Debug.WriteLine(ReadJdg(i))
>>            SQLcm.CommandText = "insert into judge values('" & ReadJdg(i) & "')"
>>            SQLcm.ExecuteNonQuery()
>>        Next
>>とすると、System.InvalidCastException
>>演算子 '&' は 文字列 "insert into judge values('" と 型 'String()' に対して定義されていません。
>>とエラーを吐きます。
>>単にSQL文作るために文字列連結したいだけなのに・・・
> 
> まず、ループで回すものが間違ってます。あと、パラメータ化しましょう。


御返答ありがとうございます。

           For i = 0 To ReadJdg.Count - 1
                Dim temp As String()
                temp = ReadJdg.Item(i)
                SQLcm.CommandText = "insert into judge values('" & temp(0) & "','" & temp(1) & "','" & temp(2) & "','" _
                                    & temp(3) & "','" & temp(4) & "','" & temp(5) & "'," & temp(6) & "," _
                                    & temp(7) & "," & temp(8) & ",'" & temp(9) & "');"
                SQLcm.ExecuteNonQuery()
            Next

とすることでうまくいきました。
tenpを作る前はSQL文字列にSystem.String(?)と入ってきて、何の事?ってなりましたが、
ここでいうtempがパラメータ化なのかな、と勝手に納得しています。
ありがとうございました。

解決済み
引用返信 編集キー/
■75262 / inTopicNo.6)  Re[5]: ArrayListとMDBのやりとり
□投稿者/ 774RR (240回)-(2015/03/09(Mon) 16:07:43)
そもそも
> 単にSQL文作るために文字列連結したいだけなのに・・・
という発想が最初から間違っているので考え直すことを強く推奨する。
連結で作った SQL 文は SQL インジェクション脆弱性を持っているので論外といっていい。

パラメタライズドクエリとか SQL インジェクションとかそういうキーワードで調べて味噌。
引用返信 編集キー/
■75264 / inTopicNo.7)  Re[5]: ArrayListとMDBのやりとり
□投稿者/ 魔界の仮面弁士 (214回)-(2015/03/09(Mon) 16:27:25)
2015/03/09(Mon) 16:31:41 編集(投稿者)

No75261 (MP枯渇ウィザード さん) に返信
> tenpを作る前はSQL文字列にSystem.String(?)と入ってきて、何の事?ってなりましたが、
> ここでいうtempがパラメータ化なのかな、と勝手に納得しています。

この場合のパラメータ化とは、SQLcm.Parameters.Add で示すことのできる SQL 内変数の事です。
VB 側の変数である tenp や temp のことではありません。


過去ログで、パラメータクエリが用いられているものを幾つか紹介。
http://bbs.wankuma.com/index.cgi?mode=al2&namber=55098&KLOG=92
http://bbs.wankuma.com/index.cgi?mode=al2&namber=6488&KLOG=17



SQL をパラメータ化した場合、SQL の作成はループ外で一度だけ行えば済みます。
これにより、JET や ACE 側での SQL 解析が効率化されますし、
temp(n) 内に『McDonald's』などといった、特殊文字を含んだデータが
含まれていても、それをエスケープ処理することなく安全に処理できます。




そもそも ArrayList で管理するのではなく、最初から
DataSet / DataTable で管理するわけにはいかないのでしょうか。
整合性チェックも行えますし、DataGridView 等への表示も容易。
データの読み書きも、DataAdapter / TableAdapter に渡すだけなので
処理がスッキリするような気がするのですが…。
引用返信 編集キー/
■75267 / inTopicNo.8)  Re[5]: ArrayListとMDBのやりとり
□投稿者/ WebSurfer (521回)-(2015/03/09(Mon) 17:56:27)
No75261 (MP枯渇ウィザード さん) に返信

質問者さんの先のスレッド ↓ で CVS のデータを DataSet / DataTable に
格納する方法を質問していましたよね。

http://bbs.wankuma.com/index.cgi?mode=al2&namber=75152

どういう訳か ArrayList を使うことに方針転換されたようですが、それが
失敗だったような気がしますよ。

その方向に進んで、さらに DataAdapter を使う方向に進んでいれば、パラ
メータ化を含めてすべてがうまくいったと思います。

再考されてはいかがですか?
引用返信 編集キー/
■75329 / inTopicNo.9)  Re[6]: ArrayListとMDBのやりとり
□投稿者/ MP枯渇ウィザード (7回)-(2015/03/16(Mon) 11:54:29)
いつもお世話になっています。
774RR様、魔界の仮面弁士様、WebSurfer様、御解答ありがとうございます。

ネットで情報が多すぎて、サンプルコードを見ながら動かして、簡単に動いたものが
ArrayListでした(紹介して頂いたリンクから使いやすそうなところを探して実装しました)。

不思議なことに現状の方法だと、SQLcm.CommandTextに(機械が吐いた)00.00.00.というデータが
temp(4)に入ってくると、それ以降の文字列が連結されず、エラーになってしまうようで、
ステップでtemp側を見ると"00.00.00."なのに、SQLcm.CommandTextで見ると、その部分が
"00.00.00. "と空白が追加されていて、上記のようにエラー。
SQLcm.CommandText.Replace(" ", "")としても空白が抜けないが、クイックウォッチで空白を削ると
データベースに書き込めるという不思議現象が発覚しました。
DataSet/DataTable、DataAdapter/TableAdapterの使用方法を学習しながら実装してみようと思います。
ありがとうございました。

一応、自動機が吐いたCSVファイルの処理専用ソフトなので、SQLインジェクションや
サニテーションについては特に考えていませんでしたが、
将来、そういう使い方をする改造が入る可能性を考えれば、当然対処すべき問題だと
認識を変えました。
御指摘ありがとうございました。

引用返信 編集キー/
■75330 / inTopicNo.10)  Re[7]: ArrayListとMDBのやりとり
□投稿者/ 魔界の仮面弁士 (237回)-(2015/03/16(Mon) 12:45:38)
2015/03/16(Mon) 12:49:03 編集(投稿者)

No75329 (MP枯渇ウィザード さん) に返信
> 不思議なことに現状の方法だと、SQLcm.CommandTextに(機械が吐いた)00.00.00.というデータが
> temp(4)に入ってくると、それ以降の文字列が連結されず、エラーになってしまうようで、

文字列データ内に ChrW(0) 相当の文字 (vbNullChar) が混入している状態だと想像します。

NULL 文字は、C 言語の文字列終端として使われているため、
たとえば TextBox 等に表示させようとすると、終端判定により
それ以降の文字が切り捨てられるといった現象が起きます。
 Dim S As String = "ABCD" & vbNullChar & "XYZ"
 TextBox1.Text = S

そのような事情から、NULL 文字を含むデータを SQL 文として処理しようとしても、
終端として切り捨てられてしまうため、正常に処理できません。

そのようなデータをデータベース内に書き込むことが本当に適切なのか、
改めて仕様を検討してみてください。

一応、VARCHAR 型のパラメータを経由させるようにすれば、たとえ NULL 文字でも
データベースに書き込むことはできますし、あるいはパラメータ化せずとも、
文字列をヘキサリテラル構文に置き換えて記載すれば、SQL に埋め込むことはできます。

ですが、たとえ NULL 文字を格納できたとしても、他の不可読文字や制御文字なども
正常に扱える保証はありません。そもそも mdb のテキスト型に記録可能な文字種は、
Jet バージョンおよび照合順序設定によって異なっているため、可読文字以外の
混入が予想されるのであれば、データベースに記録する前に、そうした文字を
捨てるか置き換えるかしておく必要があるでしょう。



> SQLcm.CommandText.Replace(" ", "")としても空白が抜けないが
空白に見えていたのは誤解で、実際には空白ではなかったと言うことでしょう。

それにそのコードだと、"Hello World" という文字列が "HelloWorld" になってしまいますよ。

もし、NULL 文字に限らず、「機械が吐いた」というあらゆるデータを保持することが目的なら、
VB 側では「バイナリデータ」としてByte配列で保持することもあわせて検討してみてください。
(機械側の仕様が分からないので、それが可能なのかどうかは分かりませんが)

バイナリをデータベースに保存したい場合、mdb 側としては
可変長の VARBINARY 型と、固定長の BINARY 型が用意されています。
(Microsoft Access のテーブルデザイナでは、これらは「バイナリ」型と表示されます)


> 一応、自動機が吐いたCSVファイルの処理専用ソフトなので、
上記回答で「NULL文字」について言及していますが、それは私の予想でしかありません。
処理されている CSV 内に コード 00 の文字が含まれているかどうかについては、
そのファイルをバイナリエディタで開くなどして確認してみて下さい。
引用返信 編集キー/
■75416 / inTopicNo.11)  Re[8]: ArrayListとMDBのやりとり
□投稿者/ MP枯渇ウィザード (8回)-(2015/03/23(Mon) 09:20:23)
No75330 (魔界の仮面弁士 さん) に返信
> 2015/03/16(Mon) 12:49:03 編集(投稿者)
>
> ■No75329 (MP枯渇ウィザード さん) に返信
>>不思議なことに現状の方法だと、SQLcm.CommandTextに(機械が吐いた)00.00.00.というデータが
>>temp(4)に入ってくると、それ以降の文字列が連結されず、エラーになってしまうようで、
>
> 文字列データ内に ChrW(0) 相当の文字 (vbNullChar) が混入している状態だと想像します。
>
> NULL 文字は、C 言語の文字列終端として使われているため、
> たとえば TextBox 等に表示させようとすると、終端判定により
> それ以降の文字が切り捨てられるといった現象が起きます。
>  Dim S As String = "ABCD" & vbNullChar & "XYZ"
>  TextBox1.Text = S
>
> そのような事情から、NULL 文字を含むデータを SQL 文として処理しようとしても、
> 終端として切り捨てられてしまうため、正常に処理できません。
>
> そのようなデータをデータベース内に書き込むことが本当に適切なのか、
> 改めて仕様を検討してみてください。
>
> 一応、VARCHAR 型のパラメータを経由させるようにすれば、たとえ NULL 文字でも
> データベースに書き込むことはできますし、あるいはパラメータ化せずとも、
> 文字列をヘキサリテラル構文に置き換えて記載すれば、SQL に埋め込むことはできます。
>
> ですが、たとえ NULL 文字を格納できたとしても、他の不可読文字や制御文字なども
> 正常に扱える保証はありません。そもそも mdb のテキスト型に記録可能な文字種は、
> Jet バージョンおよび照合順序設定によって異なっているため、可読文字以外の
> 混入が予想されるのであれば、データベースに記録する前に、そうした文字を
> 捨てるか置き換えるかしておく必要があるでしょう。
>
>
>
>>SQLcm.CommandText.Replace(" ", "")としても空白が抜けないが
> 空白に見えていたのは誤解で、実際には空白ではなかったと言うことでしょう。
>
> それにそのコードだと、"Hello World" という文字列が "HelloWorld" になってしまいますよ。
>
> もし、NULL 文字に限らず、「機械が吐いた」というあらゆるデータを保持することが目的なら、
> VB 側では「バイナリデータ」としてByte配列で保持することもあわせて検討してみてください。
> (機械側の仕様が分からないので、それが可能なのかどうかは分かりませんが)
>
> バイナリをデータベースに保存したい場合、mdb 側としては
> 可変長の VARBINARY 型と、固定長の BINARY 型が用意されています。
> (Microsoft Access のテーブルデザイナでは、これらは「バイナリ」型と表示されます)
>
>
>>一応、自動機が吐いたCSVファイルの処理専用ソフトなので、
> 上記回答で「NULL文字」について言及していますが、それは私の予想でしかありません。
> 処理されている CSV 内に コード 00 の文字が含まれているかどうかについては、
> そのファイルをバイナリエディタで開くなどして確認してみて下さい。

御返答ありがとうございます。
バイナリエディタで確認したところ、該当する箇所に00という文字が入っていました。

自動機が吐いたCSVとは言え、やはり検査結果ファイルなので、変更は拙いと思い直し、このまま何とかする方向にしました。
現在、Datasetにデータを入れる方法を調べながら、ArrayListをDatasetに改修しています。

ありがとうございました。

引用返信 編集キー/
■75417 / inTopicNo.12)  Re[9]: ArrayListとMDBのやりとり
□投稿者/ MP枯渇ウィザード (9回)-(2015/03/23(Mon) 09:21:47)
表題と内容が変わってしまっているので一旦閉じさせていただきます。
ありがとうございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -