■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 行が必要となります。
|
|