visual C# 2010 Express を使用しています。
MySqlConnectionのデータベースのコネクション部分だけを次のようなメソッドとして、
そのオブジェクトだけを得たいと思いまして、次のような感じにしたのですが、
class Program
{
static void Main(string[] args)
{
MySqlConnection conn = GetConnection();
using (MySqlCommand cmd = new MySqlCommand("SELECT * FROM tbl where id = '1'", conn))
{
conn.Open();
MySqlDataReader reader = null;
reader = cmd.ExecuteReader();
reader.Read();
int i = reader.GetInt32(reader.GetOrdinal("id"));
Console.WriteLine(i.ToString());
Console.ReadLine();
conn.Close();
}
}
static MySqlConnection GetConnection()
{
string connStr = "server=localhost;Database=test;Uid=root;Pwd=";
using (MySqlConnection conn = new MySql.Data.MySqlClient.MySqlConnection(connStr))
{
return conn;
}
}
}
一応これで表示できたのですが、
これで生成したMySqlConnectionはちゃんと開放(消滅)されているのでしょうか?
このようなやり方でデータを取得しているのを見たことがないで
大丈夫なのかな?と思いました。。
No.1
- 回答日時:
個人的には,「えっ,これで動くの?」という感じですが……。
using文は,そのブロックから出たタイミングでオブジェクトをDisposeします。
このため,GetConnectionメソッドの戻り値は「破棄されたオブジェクト」になり,
本来はOpenメソッドがObjectDisposedExceptionを発生させなければなりません。
書き換えるなら,こうでしょうか。
class Program
{
static void Main(string[] args)
{
using (MySqlConnection conn = GetConnection())
using (MySqlCommand cmd = new MySqlCommand("SELECT * FROM tbl where id = '1'", conn))
{
conn.Open();
using (reader = cmd.ExecuteReader()) // IDataReaderはIDisposableなのでDisposeを呼ぶ必要がある
{
reader.Read();
int i = reader.GetInt32(reader.GetOrdinal("id"));
Console.WriteLine(i.ToString());
} // ここでreaderが解放される
conn.Close(); // 書いた方が行儀が良いが,省略可能
} // ここでcmdとconnが解放される
Console.ReadLine();
}
static MySqlConnection GetConnection()
{
const string connStr = "server=localhost;Database=test;Uid=root;Pwd="; // constを付けておくと,変更不可能になる
return new MySql.Data.MySqlClient.MySqlConnection(connStr);
}
}
ご回答ありがとうございます。
これは今も試しましたが確かに取得できるのです。。
自分的にはもちろんなぜだかは分からないのですが、
最初はシンプルなIDisposableを継承した
class class1 : IDisposable
{
public int i = 2;
public void Dispose()
{
Console.WriteLine("Dispose");
Console.ReadLine();
}
}
でGetConnection()のような使い方を試してみたのですが、これも値が変化しました。
もしお手数でなければ、Yune-Kichiさんの環境でも試してみて頂けないでしょうか?
そして、提示して頂いたコードですが
なるほど、たしかにこのやり方ならMySqlConnectionを
GetConnectionに収めることができますね。
そもそもなんでこんなことを考えたかというと、
これも先ほどのPHPのフレームワークじゃないですけど
例えばzend frameworkのZend_Dbというクラスを使えば
http://framework.zend.com/manual/ja/zend.db.adap …
$db = Zend_Db::factory('Pdo_Mysql', $params);
$db->query();
一度$dbを作ってしまえば、あとはそれを使ってシンプル(?)な
記述で便利というか、でもそれは言語の固有の特性で
解放を自動的に行ってくれるので、このようなやり方が可能なのだと思います。
C#では当然ながら自動的に解放しないのでusingの中で処理を記述せざるえないわけですよね?
自分的にはなんとかzend frameworkじゃないですけど、それに近いクラスを
C#でも作りたい(というか慣れ親しんだイメージのまま利用したい)と思ってて、
でも言語的にさっきのオブジェクトの解放もそうですけど、
クラスやメソッドの構成に影響を与える違いもでてくるので、どうしようか悩んでいるとろこです(う~ん、うまく説明できず申し訳ないです・・・)
ちょっと漠然としすぎる質問で申し訳ないですが、もしYune-KichiさんがC#でデータベース関連のライブラリを
作成というかラップするようなクラスを作るとしたらどのように作りますか?先ほどの解放の問題も含めてですが
No.2ベストアンサー
- 回答日時:
IDisposable.Disposeは,大元はUnmanaged Resource,
つまりは.NET Frameworkが管理しないリソース,
ぶっちゃければメモリ以外のリソースの統一した解放手段を提供するための物です。
で,IDisposable自体は自分できっちり実装する必要があります。
class Class1 : IDisposable
{
private bool _disposed = false;
private int _i = 2;
~class1 () { Dispose(false); }
public int
{
get
{
if (_disposed) throw new ObjectDisposedException(); // 破棄されたオブジェクト
return _i;
}
set
{
if (_disposed) throw new ObjectDisposedExecption();
_i = value;
}
}
protected virtual void Dispose (bool disposing)
{
if (_disposed) return; // 多重Disposeしても安全であること
if (disposing)
{
// フィールドにあるIDisposableの解放等
}
_disposed = true;
}
public void Dispose ()
{
Dispose(true);
GC.SuppressFinalize(this); // ファイナライザの呼び出しを抑制する
}
}
で,本題ですが,トランザクションとかが関係しないのであれば,
Queryメソッドでコネクションを開き,DataSetなりにデータを読んで,コネクションを閉じるまでしてしまいます。
IDisposableなオブジェクトは,他のオブジェクト以上に所有権を考えないといけないため,
できるだけIDisposableなオブジェクトはusingで囲っておきたいです。
ASP.NETだとまた別の解があって,
HttpContext.Current.ApplicationInstance.EndRequestイベントで解放するように構築してしまう,というのも手です。
ASP.NETだと短い時間で処理が終わるので,終了イベントを捕まえてそこで解放しても十分,という判断です。
# 実際にこういう作りにしたことがあります。
ご回答ありがとうございます。
なるほど、自分のやり方ではちゃんと実装してなかったわけですね・・・
参考になりました。
やはりそうですか、usingで囲うしかないですかね。。
というより、考え方を変えて設計する必要がありそうですね。
これからも自分なりに作っていきたいと思います。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Java java 入力 3 4 3 出力 ABC DEFG HIJ このようなプログラムの書き方を教えてくだ 2 2022/07/15 14:18
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
- Java java final 1 2022/06/10 22:49
- C言語・C++・C# 大量のデータを読み込んで表示する速度を改善したい 8 2023/05/07 13:29
- Java Java プログラム public class Main { public static void 3 2023/08/10 23:46
- C言語・C++・C# C# DatagridviewにExcelシートを反映するとエラーが出る 2 2023/05/06 17:12
- Java JavaのSingletonパターンのprivateの持つ意味が分かりません。 5 2022/06/12 10:38
- C言語・C++・C# Windows Formアプリからコンソールを呼び出して文字を出力させたい 8 2023/05/09 10:53
- その他(プログラミング・Web制作) Sikulix2.0.5(Jython2.7.3)でcsvを読込WEB検索条件にpasteで文字化け 1 2023/03/31 11:02
- C言語・C++・C# C++プログラミングコードにポリモーフィズムを取り入れ方を教えてください。 2 2023/06/09 11:17
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBA エンターキーでイベントに...
-
アクセスVBAのMe!と[ ]
-
コードでオブジェクトを最前面に
-
現在アクティブになっているオ...
-
日本語の文字化けを直す方法
-
Excel2007 でのチェックボック...
-
エクセルVBAでセル番地を指定し...
-
カッコ付けのオブジェクト名を...
-
Imageコントロールにグラフを表...
-
VBAで選択範囲外の図形(オブジ...
-
アクセスで説明の欄の隠しオブ...
-
【エクセル】複数のTextBoxに共...
-
エクセルのデータをwebフォーム...
-
Excel VBA でPictureBoxオブジ...
-
Accessのフォーム上にエクセル...
-
VB.NET Image型データをファイ...
-
アクセスのスクロールバー
-
DLLの共有メモリと排他処理???
-
Excel VBAでマウスの左クリック...
-
【エクセルのマクロ】クリップ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
アクセスVBAのMe!と[ ]
-
VBA エンターキーでイベントに...
-
Excel VBAでマウスの左クリック...
-
文字列で小数点以下の0を削除し...
-
【エクセルのマクロ】クリップ...
-
エクセルVBAでセル番地を指定し...
-
Excel2007 でのチェックボック...
-
Accessのフォーム上にエクセル...
-
日本語の文字化けを直す方法
-
エクセルのデータをwebフォーム...
-
現在アクティブになっているオ...
-
PowerpointVBAで指定のShapeオ...
-
コードでオブジェクトを最前面に
-
【エクセル】複数のTextBoxに共...
-
Imageコントロールにグラフを表...
-
ユーザーフォームのインポート...
-
Access からオブジェクトとして...
-
構造体の静的な初期化
-
Excel VBA でPictureBoxオブジ...
-
「SHDocVw」の意味
おすすめ情報