漫ろで行こう

自由気まま過ぎる、ギークになりたい男の子の話

Posts tagged ‘Connector/Net’

© 1995-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.

© 1995-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.


会社の人に何故か質問されたのでメモ。

事の発端は、他の課の人から「無効な日付、例えば 0000-00-00 00:00:00 が含まれるデータを Connector/Net 経由でデータ抽出する場合にエラーが発生するのですが、その回避方法が掲載されているオフィシャルのドキュメントが意味不明なんです」というもの。
問題のドキュメントはこちら「MySQL :: MySQL 5.1 リファレンスマニュアル :: 24.2.4.6 Connector/NET で日付時間情報を処理する
で、問題の記述「24.2.4.6.4. 無効な日付の処理

無効な日付に MySqlDateTime を返すよう Connector/NET に指示するには、次のラインを接続ストリングに追加してください :

NotOverridable Public ReadOnly Property State As ConnectionState _
_
Implements IDbConnection.State

あー、うん。意味不明。VB での ConnectionState 取得方法な気がする。
ということで、当の本人には「公式ドキュメントが間違えている旨」と「Allow Zero Datetime を使用する旨」を伝えておきましたが、一応自分でチェックしておかないと怖いので念のため確認。

テスト環境は以下のような感じ。

  1. MySQL : 5.1.38
  2. MySQL Connector/Net : 6.1.2
  3. 言語 : C#

まずテーブルを作成してテスト用のデータを入れておく。

DROP TABLE IF EXISTS `hoge`;
CREATE TABLE `hoge` (
`id` bigint(20) auto_increment,
`str` varchar(255) DEFAULT ” NOT NULL,
`CDdate` datetime DEFAULT ’0000-00-00 00:00:00′,
`CStamp` timestamp DEFAULT NOW(),
KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO (str) values(‘a’),(‘b’),(‘c’),(‘d’);
SELECT * FROM hoge;

+—-+—–+———————+———————+
| id | str | CDdate | CStamp |
+—-+—–+———————+———————+
| 1 | a | 0000-00-00 00:00:00 | 2009-11-05 10:18:20 |
| 2 | b | 0000-00-00 00:00:00 | 2009-11-05 10:18:20 |
| 3 | c | 0000-00-00 00:00:00 | 2009-11-05 10:18:20 |
| 4 | d | 0000-00-00 00:00:00 | 2009-11-05 10:18:20 |
+—-+—–+———————+———————+

次にコードを書きますが端折ります。
基本的な書き方は System.Data.SqlClient と同様で、MySql.Data.MySqlClien を参照するだけです。
接続文字列に Allow Zero Datetime を設定しているパターンと設定していないパターンの結果が以下になります。
各出力の1行目にコネクションストリングを出力し、2行目以降に SELECT 結果を出力するようにしました。

Allow Zero Datetime 未設定

Database=test;Data Source=localhost;User Id=hoge;Password=hoge;
1 a MySql.Data.Types.MySqlConversionException: Unable to convert MySQL date/time value to System.DateTime
場所 MySql.Data.Types.MySqlDateTime.GetDateTime()
場所 MySql.Data.MySqlClient.MySqlDataReader.GetValue(Int32 i)
場所 MySql.Data.MySqlClient.MySqlDataReader.get_Item(Int32 i)
場所 AllowZeroDatetime.Program.ExecMySql(String cns) 場所 C:\test\AllowZeroDatetime\AllowZeroDatetime\Program.cs:行 43

Allow Zero Datetime 設定

Database=test;Data Source=localhost;User Id=hoge;Password=hoge;Allow Zero Datetime=True;
1 a 0000/00/00 0:00:00 2009/11/05 10:18:20
2 b 0000/00/00 0:00:00 2009/11/05 10:18:20
3 c 0000/00/00 0:00:00 2009/11/05 10:18:20
4 d 0000/00/00 0:00:00 2009/11/05 10:18:20

Allow Zero Datetime を設定していない場合、案の定 0000-00-00 00:00:00 が設定されているカラムで Exception が発生しました。設定している場合には、問題なく出力されていることが分かります。
個人的にはデフォルト値で 0000-00-00 00:00:00 を設定するのは気持ち悪いのでやりたくないですね。設定するくらいなら NULL にしておきたいですが。

ドキュメントの該当箇所に関してはフィードバックをしておきたいと思います。

© 1995-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.

© 1995-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.

所用で C# から MySQL :: Connector/Net 6.0 を利用して MySQL からデータを抜く必要があったため、コーディングしていたのですが
Fatal error encountered during command execution
といったエラーが。

原因は直ぐに特定できたのですが、どうにも腑に落ちない。
というのも、原因は条件式の検索文字列の先頭に「@」が付いているため、変数として誤認されるのが原因で回避策は後回しとして、通常の SELECT 文とプロシージャコールで挙動が異なること。
プロシージャは以下のような感じ。これで同様のエラーが発生することはなく、問題なく動作してしまう。

string hoge = "@abc";
string fuga = "asdf1234";
string query = string.Format("call proc_Test('{0}', '{1}');", hoge, fuga);

一方、通常の SELECT 文だと先述したプロシージャのようなコーディングを行うと Fatal error encountered during command execution と怒られてしまう。
対処方法としては以下のような感じにする必要がある。

string cns = "MySQL接続文字列";
string hoge = "@abc";
string fuga = "asdf1234";
string query = string.Format(
  "select * from atTest where testName=@TEST and testPass='{0}';", fuga);
using (MySqlConnection conn = new MySqlConnection(cns))
{
  MySqlCommand cmd = new MySqlCommand(query, conn);
  cmd.Parameters.Add(new MySqlParameter(
    "@TEST", MySqlDbType.VarChar, 40));
  cmd.Parameters["@TEST"].Value = hoge;
  cmd.CommandTimeout = 300;
  conn.Open();
  // 処理
  conn.Close();
}

後者も完璧ではないけども(fuga 変数の内容も本来であれば、Parameters に Add するべきなんだけど)プロシージャの場合は問題無いのはどういうことだろう?
Conncector/Net のバグなのか仕様なのか……。

official.MySQL Query Analyzer – Improving SQL Query Performance

Get Adobe Flash playerPlugin by wpburn.com wordpress themes
Proudly powered by WordPress. Theme developed with WordPress Theme Generator.
Copyright © 漫ろで行こう. All rights reserved.