QA@IT
この質問・回答は、@ITの旧掲示板からインポートされたものです。

Transaction 処理について

こんにちは。Transaction処理について、困っているので投稿しました。
VB.NETでの開発です。サーバはOracle9iR2、プロバイダはODP.NETを使用します。
-----------------------
Dim cn As New Oracle.DataAccess.Client.OracleConnection() 'コネクション
Dim cmd As New Oracle.DataAccess.Client.OracleCommand() 'コマンド
Dim myTrans As Oracle.DataAccess.Client.OracleTransaction 'トランザクション

cn.ConnectionString = "接続文字列"
cn.Open()
cmd.Connection = cn
myTrans = cn.BeginTransaction()
cmd.Transaction = myTrans <--- ココ
-----------------------
矢印の部分に、「プロパティ'Transaction'は'ReadOnly'です」というメッセージが出て、トランザクションを設定できません。
サンプル等見ながら書いたつもりなのですが、何か抜けている設定などがあるのでしょうか?どなたか、ご存知の方、アドバイスをよろしくお願いします!

質問者:りん

回答

Oracle Database starts a transaction only in the context of a connection. Once a
transaction starts, all the successive command execution on that connection run in the
context of that transaction. Transactions can be started only on an
OracleConnection object, and the read-only Transaction property on the
OracleCommand object is implicitly set by the OracleConnection object. Therefore,
the application cannot set the Transaction property, nor does it need to.

設定する必要はありません。

投稿者:未記入

編集 履歴 (0)

どうにも誤解があるようですが…

これはODP.NETの仕様です。
ODP.NETでは、コマンドにトランザクションを設定する必要はありません。
DbCommandだったか、基底の型にキャストすれば代入できますが、必要ありません。

まあ正直、通常のADO.NETの使い方を変えてしまっていて、あまりいい気はしないんですけどね。
一応、ODP.NETのドキュメントにはちゃんと書かれてたはずです。

--追記
すみません、2ページ目を見落としてましたごめんなさい。
っていうかしかも元はすごい昔の投稿ですね…嗚呼…
[ メッセージ編集済み 編集者: なちゃ 編集日時 2009-04-17 22:51 ]

投稿者:なちゃ

編集 履歴 (0)

こんにちはNYRLです。

コマンドをコネクションから作成してもダメですか?

Dim cmd As Oracle.DataAccess.Client.OracleCommand() = cn.CreateCommand()

SQLServerでやっていた時に new したコマンドに代入できなかった
記憶があります。

[ メッセージ編集済み 編集者: NYRL 編集日時 2003-07-22 11:28 ]

投稿者:NYRL

編集 履歴 (0)

-------------
'Dim cmd As New Oracle.DataAccess.Client.OracleCommand() コメントにしました
'cmd.Connection = cn コメントにしました

cn.Open()
Dim cmd As Oracle.DataAccess.Client.OracleCommand() = cn.CreateCommand()
myTrans = cn.BeginTransaction()
cmd.Transaction = myTrans
-------------
ううん、試してみたのですが、
やはり、同じ場所で「ReadOnlyです」というメッセージがでます。。

投稿者:りん

編集 履歴 (0)

cmd.Transaction = myTrans

読み取り専用プロパティなので、設定不可能です。

下記のとおり試してみてください。

OracleTransaction txn;
OracleCommand cmd;

txn = con.BeginTransaction();
cmd = new OracleCommand("", con);

# C#ですみません...。

投稿者:なな

編集 履歴 (0)

NYRLさん、ななさん、ありがとうございます。

>読み取り専用プロパティなので、設定不可能です
そうだったんですね・・・

------
Dim cn As New Oracle.DataAccess.Client.OracleConnection()
Dim cmd As Oracle.DataAccess.Client.OracleCommand
Dim myTrans As Oracle.DataAccess.Client.OracleTransaction

cn.Open()
myTrans = cn.BeginTransaction()
cmd = new OracleCommand("", cn)
cmdDelete.CommandText = "delete from 社員テーブル where 氏名='テスト'"
Call cmdDelete.ExecuteNonQuery
myTrans.Commit
-------
例えばですが、上記ようなやりかたでうまくいきました!
どうもありがとうございました!

投稿者:りん

編集 履歴 (0)

MSDNによると

Transaction プロパティに既に特定の値が設定されていて、コマンドが実行中の場合は、このプロパティは設定できません。 OracleCommand オブジェクトと同じ OracleConnection に接続されていない OracleTransaction オブジェクトをトランザクション プロパティに設定すると、次回のステートメント実行時に例外がスローされます。

となっていてOracleTransaction のサンプルでは

Dim myConnection As New OracleConnection(myConnString)
myConnection.Open()

Dim myCommand As OracleCommand = myConnection.CreateCommand()
Dim myTrans As OracleTransaction

myTrans = myConnection.BeginTransaction(IsolationLevel.ReadCommitted)
myCommand.Transaction = myTrans

となっているので順番に気をつければ代入できるはずなんですけどね・・・

とりあえずできたからいいのかな)

投稿者:NYRL

編集 履歴 (0)

順番に気をつければ代入できるはず

なるほど!まさにこのページを参考にしていたんですが、確かに、
自分の作りたいようにプログラムの順番を換えていました。
その結果、上記のようなことが起こっていたんですね。
本当にどうもありがとうございました!

投稿者:りん

編集 履歴 (0)

MSDNによると

恐れ入ります。
念のために、C# + ODP.NETで確認していますが、どうしても代入できません。

OracleConnection con = new OracleConnection("...");
con.Open();
OracleCommand cmd = con.CreateCommand();
OracleTransaction txn = con.BeginTransaction();
cmd.Transaction = txn; // ← ここでコンパイルエラー発生!

MSDNのどこにサンプルが記述されているか教えていただけませんか?

# ちなみに、わたしはODP.NETのOracleTransaction Classに書かれているサンプルを参考にしました。

投稿者:なな

編集 履歴 (0)

こんにちは。

 おそらく、Oracle Data Provider for .NETと、.NET Framework Data Provider for Oracleが混乱していると思われます。
NYRLさんのサンプルは、.NET Framework Data Provider for Oracleの方にありました。
りんさん、ななさんが問題にされているのはOracle Data Provider for .NETですよね?
Oracle Data Provider for .NETのサンプルでは、トランザクションはOracleDbCommand.Transactionに代入せずに使用されています。ここの説明では、

When this property is accessed through an IDbCommand reference, its set accessor method is not operational.

「IDbCommandより参照される場合はリードオンリーである」とあります。

投稿者:Jitta

編集 履歴 (0)

Jittaさんフォローありがとうございますそのとおりでした
私が混乱させたみたいですいませんでした

投稿者:NYRL

編集 履歴 (0)

りんさん、ななさんが問題にされているのはOracle Data Provider for .NETですよね?

そうでした、
私が見たサンプルも SQLServer用のサンプルで、
ODPとも.net for oracleとも違っていました。。。
すみません。

ODP.NETを使用したサンプルがあまり無いのでいつもとても助かります。

投稿者:りん

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。