@IT会議室は、ITエンジニアに特化した質問・回答コミュニティ「QA@IT」に生まれ変わりました。ぜひご利用ください。
- PR -

C#からMySQLにバイナリ(画像)データを登録したい

1
投稿者投稿内容
Soony
会議室デビュー日: 2005/11/09
投稿数: 7
投稿日時: 2006-11-12 15:52
こんにちは。Soonyと申します。

VS2003 C# + SQL Server2000 + MySQL4.1 間で連携しているWindowsアプリを動かしています。
MySQLへの接続には、MySqlConnector1.0.8を使っています。

SQL Serverにバイナリで保存されている画像データを、
FedoraCore5上にあるMySQLのBLOB型フィールドへコピーしたいと考えているのですが、
C#コード上で、バイナリデータ化するところでつまづいています。


作っているコードは、以下のような感じにしています。

---------

SqlParameterObject sqlObj = new SqlParameterObject();
Hashtable param = new Hashtable();

// 物件情報登録SQL
sqlUpdFac += " INSERT INTO TBL_FACILITY VALUES(………); ";

// フロア情報登録SQL
・・・
foreach (DataRow rowFlr in tableFlr.Rows) {
sqlUpdFac += " INSERT INTO TBL_FLOOR VALUES( ………); ";
}

// 画像情報の登録SQL
// SQL Serverから画像データを取得
string sqlImg = " SELECT * FROM TBL_IMAGE WHERE facility_no = @facility_no AND image_no = 1 ";
param.Clear();
param["@facility_no"] = "00000001";
sqlObj.reset();
sqlObj.QueryString = sqlImg;
sqlObj.HashParameter = param;
DataTable tableImg = access.Select(sqlObj);
foreach (DataRow rowImg in tableImg.Rows) {

// このあたりをいろいろいじってはいるのですが・・・
Byte[] byteData = (Byte[])(rowImg["image_data"]);

MemoryStream stream = new MemoryStream();
stream.Read(byteData, 0, Convert.ToInt32(stream.Length));

// 問題はココ
sqlUpdFac += " INSERT INTO TBL_IMAGE VALUES(" +
"'" + rowImg["facility_no"].ToString() + "', " +
"'" + byteData + "'); " +
}

command = new MySqlCommand(sqlUpdFac, conn);
int ret = command.ExecuteNonQuery();

---------

このコードを実行すると、BLOBフィールドに、"System.Byte[]"という文字列が登録されてしまい、
望む結果が得られません。
(それ以外のデータは、正常に登録されています。)

Byteデータに変換するあたりなど、いろいろいじってみてはいるのですが、
結果は変わりません。


もしかすると、SELECT文を使ってレコードセットオブジェクトを生成して、
Open→値の代入→Update→Close
とすればすんなりいくのかもしれませんが、
上記のコードのように、一度に複数のクエリを実行させたいこと、
また、MySqlConnectorを使用することははずせないことから、
直接INSERT文にて、バイナリデータの登録ができないものかと悪戦苦闘しております。


以上ですが、よい方法などはありませんでしょうか。
よろしくお願いいたします。

念のため、これまでに参考にした記事をあげておきます。
http://support.microsoft.com/default.aspx?scid=kb;ja;316887
http://ml.php.gr.jp/pipermail/php-users/2003-April/015326.html
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2006-11-12 22:19
引用:
このコードを実行すると、BLOBフィールドに、"System.Byte[]"という文字列が登録されてしまい、
望む結果が得られません。

ToString()はoverrideされない限り型の名前を返しますからね。
byte配列をstringに変換したいのならSystem.Text.EncodingのGetString(byte[])を使います。
ただし、どのエンコーディングでstring可するのか、というのを決めなければなりません。
#これでMySqlにINSERTする方法は(できるのかも)知りませんが。
かるあ
ぬし
会議室デビュー日: 2003/11/16
投稿数: 1190
お住まい・勤務地: センガワ→ムサシノ
投稿日時: 2006-11-12 22:39
実際に MySQL で BLOB 型のフィールドを更新したことは無いのですが、
参考にしている一つ目の URL にある パラメータクエリ を使った方法は試してみましたか?

HOW TO では OleDb を使っているところを MySqlConnector に読み替えてあげる必要はあるかと思いますが。。。
Soony
会議室デビュー日: 2005/11/09
投稿数: 7
投稿日時: 2006-11-13 00:13
ご回答、ありがとうございます。

かるあさん>>
引用:

かるあさんの書き込み (2006-11-12 22:39) より:
実際に MySQL で BLOB 型のフィールドを更新したことは無いのですが、
参考にしている一つ目の URL にある パラメータクエリ を使った方法は試してみましたか?

HOW TO では OleDb を使っているところを MySqlConnector に読み替えてあげる必要はあるかと思いますが。。。



実は、質問を投げる前まで、パラメータクエリも試していたんですが、
いろいろエラーが出ていて、それが何かを追求するのに苦労していて、
ちょっと疲れ果ててサジを投げていたところでした。

が、小休止をしてコードを見直したところ、なぜか解決まで漕ぎ着けてしまいました。

ということで結論としては、パラメータクエリを使用することでできたようです。
コードは以下のようになりました。

  string sqlGetImg = " SELECT * FROM TBL_IMAGE WHERE facility_no = @facility_no ";
  string sqlUpdImg = " INSERT INTO TBL_IMAGE VALUES(?facility_no, ?row_no, ?image_data);";
  
  foreach (… facility_no によるループ …) {
    
    // …… このあたりで、フロア情報やその他の情報のMySQLへの登録を実行
    // …… ホントは以下の画像データと一緒に一気に複数の1コマンドでSQLを流したかったが...orz
    
    // SQL Serverから画像取得
    param.Clear();
    param["@facility_no"] = row["facility_no"].ToString();
    sqlObj.reset();
    sqlObj.QueryString = sqlGetImg;
    sqlObj.HashParameter = param;
    DataTable tableImg = access.Select(sqlObj);
    
    // MySQLへ画像登録
    foreach (DataRow rowImg in tableImg.Rows) {
      Byte[] byteData = (Byte[])(rowImg["image_data"]);
      MemoryStream stream = new MemoryStream();
      stream.Read(byteData, 0, Convert.ToInt32(stream.Length));
      
      cmdImg.Parameters.Clear();
      cmdImg.Parameters.Add(new MySqlParameter("?facility_no", rowImg["facility_no"].ToString()));
      cmdImg.Parameters.Add(new MySqlParameter("?row_no", rowImg["row_no"].ToString()));
      cmdImg.Parameters.Add(new MySqlParameter("?image_data", byteData));
      cmdImg.ExecuteNonQuery();
    }
  }

バイナリ変換しているところは、質問投稿時のコードをほぼそのままでいけました。

できれば、facility_noごとに一括に登録と思ったのですが、
1つのfacility_noあたりに、十数件の画像データが登録されている可能性があり、
stream.Readメソッド実行時に、メモリにたくさん据え置かなければならない可能性があることを考えると、
少々怖い気がしたので1件ずつ処理することにしました。

余談ですが、上記は、MySqlConnector/net というDriverを使用していたんですが、
http://www.mysql.com/products/connector/net/
ODBCConnectorも、普通に使えたんですね。...当たり前ですね...orz
ソースもまったく一緒で、MySql…となっているところが、ODBC…となるだけでした。

処理スピード的にはどうなんでしょうか?
MySqlConnectorはセットアップをしてあげないと使えないことを考えると、
ODBCの方が確実だったりする気がします。。。



以上報告になりますが、この投稿を持って解決とさせていただきます。
ご回答くださった方々、ありがとうございまいた。
Soony
会議室デビュー日: 2005/11/09
投稿数: 7
投稿日時: 2006-11-13 00:18
引用:

余談ですが、上記は、MySqlConnector/net というDriverを使用していたんですが、
http://www.mysql.com/products/connector/net/
ODBCConnectorも、普通に使えたんですね。...当たり前ですね...orz
ソースもまったく一緒で、MySql…となっているところが、ODBC…となるだけでした。

処理スピード的にはどうなんでしょうか?
MySqlConnectorはセットアップをしてあげないと使えないことを考えると、
ODBCの方が確実だったりする気がします。。。



追記になりますが、以下の記事が、上記の解決に至ったきっかけになったものです。
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=33554&forum=7

少々パラメータの書き方が違っているようではありますが、
ここの記事でODBCでのコードが書いてあって、気がついたのでした。。。
1

スキルアップ/キャリアアップ(JOB@IT)