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

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

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

Re[2]: C#でADOを使用する方法


(過去ログ 19 を表示中)

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

■7478 / inTopicNo.1)  C#でADOを使用する方法
  
□投稿者/ aca (1回)-(2007/09/06(Thu) 15:28:23)

分類:[C#] 

すみません、非常に単純な問題だと思うのですがご教授ください。

C#で、ADO2.8を使用してデータベースアクセス(mdb)しようと考えています。
しかし、ADODBの各オブジェクトのメソッドで、エラー
「引数を***個指定できるメソッド***のオーバーロードはありません」
になってしまうのです。
たとえば、以下のような単純なコードでも、cn.Openや、rs.Updateでエラーになってしまいます。

ADODB.Connection cn = new ADODB.Connection();
cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\test.mdb;";
cn.Open();
ADODB.Recordset rs;
rs = cn.Execute("select * from test");
rs.AddNew();
rs.Fields("name").value = "test";
rs.Update();
rs.Close();

MSDN等のリファレンスを見ても、省略できる引数しか省略していないはずなので、
なんでタイプライブラリ参照してるのにオーバーロード解決しないんだよ〜と泣きそうです。

くだらなさすぎて申し訳ありませんが、どうぞご教授ください。
よろしくお願いします。
引用返信 編集キー/
■7480 / inTopicNo.2)  Re[1]: C#でADOを使用する方法
□投稿者/ 魔界の仮面弁士 (412回)-(2007/09/06(Thu) 16:44:56)
2007/09/06(Thu) 16:54:46 編集(投稿者)

No7478 (aca さん) に返信
> C#で、ADO2.8を使用してデータベースアクセス(mdb)しようと考えています。

止めておいた方が無難です。

.NET からの ADO の利用は推奨されていません。
かわりに、ADO.NET の利用を検討してみてください。


それでも、どうしても ADO の機能を必要としているのであれば、一応、参考情報を。

[.NET での ADO の使用に関するロードマップ]
http://support.microsoft.com/kb/308044/ja-jp

[高負荷下で ADO を .NET COM interop または Java で使用するとアクセス違反が発生する]
http://support.microsoft.com/kb/321415/ja

[Visual Studio .NET で ADO (ADODB) のプライマリ相互運用アセンブリを使用する]
http://support.microsoft.com/kb/318559/ja


> MSDN等のリファレンスを見ても、省略できる引数しか省略していないはずなので、
C# の言語仕様では、「省略可能な引数」がサポートされていないため、引数を省略できません。

たとえば、Connection.Open は 4個の「省略可能な引数」を受け取る仕様になっていますが、
この場合は、cn.Open(); のような表記方法ではなく、それぞれの引数を指定するために
cn.Open(null, null, null, (int)ADODB.ConnectOptionEnum.adConnectUnspecified);
といったコードが要求されます。他のメソッドについても同様です。


> ADODB.Connection cn = new ADODB.Connection();
上で紹介した URL にも説明がありますが、インスタンス生成には、
new ADODB.Connection(); ではなく、new ADODB.ConnectionClass(); を使ってください。


> cn.Open();
これについては先述の通り。引数は省略できません。


> rs = cn.Execute("select * from test");
引数を省略できませんので、この場合はたとえば、
 object affected = Missing.Value;
 rs = cn.Execute("select * from test", out affected,
  (int)ADODB.CommandTypeEnum.adCmdText);
のようにします。


> rs.AddNew();
これも同じ。rs.AddNew(Missing.Value, Missing.Value); ですね。

ただし、このコードだと、コンパイルは通るものの、実行時に例外が発生してしまうでしょう。
何故なら、Connection.Execute メソッドから得た Recordset は更新できない仕様だからです。
(LockType == adLockReadOnly, CursorType == adOpenForwardOnly となります)

更新可能な Recordset を得たいのであれば、Command オブジェクトを使うか、または
Recordset.Open メソッドを使うようにしてみてください。たとえば、
rs = cn.Execute(〜); の行を削除し、以下の 2 行に置き換えるようにします。

rs = new ADODB.RecordsetClass();
rs.Open(
  "select * from test", cn,
  ADODB.CursorTypeEnum.adOpenStatic,
  ADODB.LockTypeEnum.adLockOptimistic,
  (int)ADODB.CommandTypeEnum.adCmdText
);

このようにすれば、更新可能な Recordset となるので、AddNew 等が使えるようになります。


> rs.Fields("name").value = "test";
それは、VB 系言語で使われる構文です。C# では使えません。

まず、C# は大文字小文字を区別する言語ですので、
value プロパティを Value プロパティに改める必要があります。

次に、C# は「引数を持ったプロパティ」をサポートしていないため、
それらはインデクサ等にマッピングされる仕様です。すなわち、
rs.Fields("name") ではなく rs.Fields["name"] となります。

もう一つ注意すべきは、ADODB の PIA を用いているかどうかです。(先述のURL参照)
PIA の場合は上記の構文で構わないのですが、そうでは無いのであれば、
 ADODB.Fields fields = rs.Fields;
 ADODB.Field field = fields["name"];
 field.Value = "test";
のように、個々のオブジェクトを変数に取っておき、後から、
 Marshal.ReleaseComObject(field);
 Marshal.ReleaseComObject(fields);
 Marshal.ReleaseComObject(rs);
のように、COM オブジェクトの解放処理が行えるようにしておく必要があります。

一方、PIA の場合は、Fields や Field がマネージオブジェクトになっているため、
これらのオブジェクトについては、ReleaseComObject メソッドの呼び出しが不要です。

ただし、すべてのオブジェクトがマネージになっているわけでは無く、PIA といえども、
Recordset や Connection は COM オブジェクトのままになっていますので、これらに
ついては、依然として ReleaseComObject の呼び出しが必要となります。

なお、これは蛇足ですが、今回のような AddNew 作業においては、
 rs.AddNew("name", "test");
のように指定すると、Field クラスを経由せずに書き込めるので便利ですよ。
複数の列を更新する場合には、
 rs.AddNew(new object[] { "Field1", "Field2" }, new object[] { "Value1", "Value2" });
のように、配列で指定できます。


> rs.Update();
引数指定が省略できないということで、ここもエラーとなるはずです。
rs.Update(Missing.Value, Missing.Value); のように変更しておいてください。

なお、Update メソッドも、AddNew メソッド同様、フィールド名と値の一覧を渡すことで、
Field クラスを経由せずに、該当行のデータを更新できるようになっています。


> rs.Close();
COM オブジェクトの解放作業等が必要なので、実際にはその後に、
 Marshal.ReleaseComObject(rs);
 cn.Close();
 Marshal.ReleaseComObject(cn);
という 3 行が必要となります。
引用返信 編集キー/
■7485 / inTopicNo.3)  Re[2]: C#でADOを使用する方法
□投稿者/ aca (2回)-(2007/09/06(Thu) 17:11:58)
質問させていただいたacaです。
本当に丁寧にご教授いただき、感激です。
(同時に自分の勉強不足にげんなりです)

> 止めておいた方が無難です。
>
> .NET からの ADO の利用は推奨されていません。
> かわりに、ADO.NET の利用を検討してみてください。

たしかに・・・激しく納得です。
ADOのメソッドの省略可能とは、言葉のとおり省略可能なのであってオーバーロードではないのですね。
うう、情けない。
ADOなら以前にしょっちゅう使用していたので、ActiveX使えるなら・・・と思っていましたが、
ADO.NETに切り替えることにします。

まだ、ご教授いただいたURLにすべて目を通すまでには至っていませんが、まずはお礼とご報告まで。
また、PIAやAddNewの使用方法なども目からウロコで大変参考になりました。
本当にありがとうございました。

解決済み
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -