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

オブジェクト参照エラーについて

ASP.NETでWebアプリを開発しているのですが、

同じプログラム、同じ環境で、
「オブジェクト参照がオブジェクト インスタンスに設定されていません」というエラーが出るときと出ないときがあります。

皆様はこのようなご経験はありますか?

もしこのようなエラーが出た場合の対処方法などがありましたらご教授ください。

質問者:taro

回答

taroさんの書き込み (2003-08-26 13:38) より:

ASP.NETでWebアプリを開発しているのですが、

同じプログラム、同じ環境で、

「オブジェクト参照がオブジェクト インスタンスに設定されていません」というエラーが出るときと出ないときがあります。

同じプログラム、同じ環境とありますが、他の条件もすべて同じですか?
遷移元ページは同じですか?遷移元ページで入力したデータは同じですか?
そのページで(DBなどから)参照しているデータの内容は同じですか?
それらがまったく同じでないなら、普通に起こりうることです。

NullReferenceExceptionが起きているだけなので、
こういう場合はほぼ間違いなく自分のプログラムの不具合です。

使用している変数で初期化していないものはないですか?
遷移元ページからSessionなどで引き渡されている情報はnull(Nothig)ではないですか?

もしこのようなエラーが出た場合の対処方法などがありましたらご教授ください。

どこで発生しているか?を突き止めて、どのデータがnullになっているか確認し、
それに応じて原因となっている個所を修正します。

後、「ここではxxxというデータが渡されてくるはず」といったような仮定はせずに、
本当にその通りになっているかどうかエラーチェックをするようにした方がよいでしょう。

投稿者:よねKEN

編集 履歴 (0)

よねKEN さま

ご指摘ありがとうございます。

質問をしておきながらあいまいな問いかけで申しわけありませんでした。

もう一度質問を書き直しますと

遷移元も遷移先も同じ、入力した条件も同じ、DBからデータを取得するSQL文も同じ時に
データを取得して配列で返す場合とデータを取得できずにNothingで返す場合があります。
その結果、そのあとのデータの表示部でオブジェクト参照エラーが発生してしまいます。

コードは下記のような感じで書いてあります。

 [例]

dim strData() as string  'データ格納配列
 dim strSql as string 'SQL文

clsdb.DBConnect() 'データベースに接続
clsdb.DBQuery(strSql) 'SQL実行
strData = clsdb.GetData() 'データの取得

 if strData(0) = "0000" then ←オブジェクト参照エラー発生場所
.
.
.

投稿者:taro

編集 履歴 (0)

 こういう場合、とりあえずブレークポイントを張って、SQL文が意図したとおりに構成されているか調べます。

 こっちのページでは発生せず、あっちのページでは必ず発生するというのであれば、Webアプリケーションの特性(ユーザからのアクションを受けるときは、毎回新しいオブジェクトが作成されている)を理解していないためと思われます。

投稿者:Jitta

編集 履歴 (0)

taroさんの書き込み (2003-08-26 15:52) より:

 [例]

dim strData() as string  'データ格納配列

 dim strSql as string 'SQL文

clsdb.DBConnect() 'データベースに接続

clsdb.DBQuery(strSql) 'SQL実行

strData = clsdb.GetData() 'データの取得

 if strData(0) = "0000" then ←オブジェクト参照エラー発生場所

そこで例外があがっているのであれば、

clsdb.GetData() 'データの取得

が期待するデータを返していないと思われます。

clsdbという変数の型は何でしょう。
使用しているメソッドの名前からすると独自のクラスと思いますが、
DBConnectメソッドは正常に処理されていますか?

例えば、内部でExceptionをCatchしつつ、エラーがあがっていても無視していれば、
コネクションを貼るのに失敗したまま処理を続行しているというようなこともありえます。
また、接続が成功したかどうかを戻り値で戻しているようなタイプのメソッドであれば、
その値をチェックする必要もありますが、
提示の情報からでは私にはその辺りに問題がないのかどうか判断できませんので
ご自身でご確認ください。
次の、DBQueryメソッドも同様に正常に処理されているかご確認ください。

後は、念のため、strSqlの中身を使用しているDBMSのツールなどから流して、
正常に結果を取得できるかどうか確認しましょう。

そこまでOKであれば、GetDataメソッドの中身も順に確認しましょう。

投稿者:よねKEN

編集 履歴 (0)

データを取得して配列で返す場合とデータを取得できずにNothingで返す場合があります。

その結果、そのあとのデータの表示部でオブジェクト参照エラーが発生してしまいます。

dim strData() as string  'データ格納配列

  .

  .

  .

strData = clsdb.GetData() 'データの取得

 if strData(0) = "0000" then ←オブジェクト参照エラー発生場所

  .

  .

  .

Nothingで返されるんだったらそれはもうエラーになりそうな気がしますが…

投稿者:なちゃ

編集 履歴 (0)

皆様 ご指摘ありがとうございました。

皆様のご指摘のように一つ一つブレイクポイントを立てチェックした結果、
Olacleに接続できている場合とできていない場合で私が質問したエラーが起こることが分かりました。

現状では、なぜOlacleに接続できる場合とできない場合があるのかを調査中です。

投稿者:taro

編集 履歴 (0)

taroさんの書き込み (2003-08-26 19:04) より:

現状では、なぜOlacleに接続できる場合とできない場合があるのかを調査中です。

 Exceptionが発生していると思いますが、Exception.Messageはご覧になりましたか?また、Exceptionの型も重要な情報です。すべてをわかってExceptionをキャッチしているならよいのですが、そうでないなら、まずはExceptionを受けずにメッセージを表示させ、一通りのテスト終了後に受けるように修正する、とした方がよいでしょう。
 せっかく提供されている情報があるのにそれを利用しないなら、時間と労力を無駄にするだけですよ。

投稿者:Jitta

編集 履歴 (0)

Jitta さま

ご指摘ありがとうございました。

Exceptionのエラーメッセージのことは知っていましたが、エラー内容が
「呼び出しのターゲットが例外をスローしました。」というもので、
これが何に起因して発生しているのかが調べてもわかりませんでした。

質問をしておきながら、エラーの正確な情報を提供せずに申し訳ありません。

投稿者:taro

編集 履歴 (0)

taroさんの書き込み (2003-08-27 09:01) より:

Exceptionのエラーメッセージのことは知っていましたが、エラー内容が

「呼び出しのターゲットが例外をスローしました。」というもので、

これが何に起因して発生しているのかが調べてもわかりませんでした。

 Exception.InnerExceptionは、ご存じですか?今見ている例外の発生元となった例外の情報です。再帰的に潜ってすべてのMessageを見ると、原因が書いてあるかもしれません。
 また、Exceptionで受けていても、生成されたオブジェクトの型は変わらないので、Exception.GetType().ToString()で、なんという例外が発生したのかがわかります。その型にキャストすると、より有用な情報が表示できる可能性があります。例えば、OleDbExceptionが発生しているのであれば、Errorsプロパティにより、OLEで発生したエラーの詳細を参照できます。
←キャストするのではなく、元からその型で受けるようにしてください。
try
catch ex as oledbexception
catch ex as argumentexception
catch ex ...
end try

 例外は、多くの場合「エラー処理」といわれますが、「例外的な状況が発生した場合の、状況情報を収集する手段」でもあるので、有効に活用してください。←逆に言えば、自分が例外を生成するときはそれだけの情報を詰め込むように気を配れ、ということ。

投稿者:Jitta

編集 履歴 (0)

Jitta さま

ご指摘ありがとうございます。

ご指摘のようにException.InnerExceptionのMessageを見てみると
「Oracle エラーが発生しましたが、エラー メッセージは Oracle から取得できませんでした。」とありました。

 olacleエラーメッセージを取得しようとして、以下のようなコードを書いたのですが、肝心なoledbExceptionのほうには入りませんでした。

 どこかコーディングの仕方に間違いがあったのでしょうか?

 strDBName = "DataBase"
strUser = "User1"
strPassword = "Password"

Try
strConnect = "Provider=MSDAORA; Data Source=" + strDBName + "; User ID=" + strUser + "; Password=" + strPassword

 objConnect = New OleDb.OleDbConnection(strConnect)
 objConnect.Open()

Catch ex As OleDb.OleDbException
  'error処理

Catch ex As Exception
'error処理
End Try

投稿者:taro

編集 履歴 (0)

taroさんの書き込み (2003-08-29 10:34) より:

ご指摘のようにException.InnerExceptionのMessageを見てみると

「Oracle エラーが発生しましたが、エラー メッセージは Oracle から取得できませんでした。」とありました。

 olacleエラーメッセージを取得しようとして、以下のようなコードを書いたのですが、肝心なoledbExceptionのほうには入りませんでした。

 エラーになる場合と、ならない場合で、接続文字列が変わったりしていませんか?
 使い終わった接続を、ちゃんと閉じていますか?接続数が上限に達しているとかの問題ではないでしょうか?

 例外の型は、とりあえずcatch ex as exceptionの中に、
debug.writeline(e.message, e.gettype.tostring)
を入れてください。すると、「出力」ウインドウにメッセージと型が表示されます。それを頼りにcatchを増やしてください。なお、innerexceptionの例外を拾うことはできません。それは内部でキャッチされ、他のexceptionに変換(という言い方が正しいとは思わないが)されて送出されているからです。

投稿者:Jitta

編集 履歴 (0)

Jittaさま

ご指摘ありがとうございました。

ご指摘のとおりにDebug.WriteLineをいれいろいろとやっている最中です。

また、なにか壁にぶつかりましたら質問させていただきます。

投稿者:taro

編集 履歴 (0)
ウォッチ

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