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

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

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

Re[8]: プロシージャの戻り値がnullの時


(過去ログ 93 を表示中)

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

■55721 / inTopicNo.1)  プロシージャの戻り値がnullの時
  
□投稿者/ ペンギン (1回)-(2010/12/10(Fri) 15:23:43)

分類:[C#] 

お世話になっております。
現在C#での開発をおこなっていて行き詰ったのでご質問させていただきます。

以下環境で開発を行っています。
OS :Windows7
開発ツール :VisualStudio2010
開発言語 :C#
ミドルウェア:.NetFrameWork4.0
Oracle :OracleDatabase 9.2.0.8
    Oracle Client 11.2.0
     Oracle Data Provider for .NET 4 11.2.0.1.2
     Oracle Provider for OLE DB 11.2.0.1.0
[現象]
画面からPL/SQLのストアドプロシージャをコールし、戻り値を画面に表示
する処理で不具合が発生しています。

処理の内容をざっくりと説明しますと、
Oracle.DataAccess.Client.OracleDataAdapterクラスから作成されたオブジェクトの値を
Hashtableに格納し、それをString型の変数に格納して文字列を画面に表示しています。
この時、戻り値がnullだと画面に「NULL」と表示されてしまいます。

調べてみたところ、Hashtableに値を格納する際に、nullが"NULL"という文字列に変換されていました。

さらに、PL/SQLの戻り値がnullの時Oracle.DataAccess.Client.OracleDataAdapter
クラスから作成されたオブジェクトのvalue値でエラーが発生していました。
Value値に「型 'Oracle.DataAccess.Types.OracleNullValueException' の例外をスローしました。」
というエラーメッセージが出力され、Value直下のbaseに
"NULLデータの処理が無効です。"と出力されます。

[質問]
http://otndnld.oracle.co.jp/document/products/oracle10g/102/windows/B31247-01/OracleNullValueExceptionClass.htm

こちらを見た限りこのエラーは、「NULL値が含まれるODP.NETタイプ構造にアクセスを試みたときに表示される例外」との
ことですが、OracleDataAdapterクラスから作成されたオブジェクトの値にはNULLを格納してはいけないということなのでしょうか?

分かりづらい文章で申し訳ございません。
必要な情報が足りなかったら補足します。
どうぞよろしくお願いいたします。
引用返信 編集キー/
■55728 / inTopicNo.2)  Re[1]: プロシージャの戻り値がnullの時
□投稿者/ shu (275回)-(2010/12/10(Fri) 22:27:21)
No55721 (ペンギン さん) に返信

> [現象]
> 画面からPL/SQLのストアドプロシージャをコールし、戻り値を画面に表示
> する処理で不具合が発生しています。
>
> 処理の内容をざっくりと説明しますと、
> Oracle.DataAccess.Client.OracleDataAdapterクラスから作成されたオブジェクトの値を
ここで言うオブジェクトというのはDataSetですか?


> Hashtableに格納し、それをString型の変数に格納して文字列を画面に表示しています。
> この時、戻り値がnullだと画面に「NULL」と表示されてしまいます。
>
> 調べてみたところ、Hashtableに値を格納する際に、nullが"NULL"という文字列に変換されていました。
どのように処理を行っていますか?


> さらに、PL/SQLの戻り値がnullの時Oracle.DataAccess.Client.OracleDataAdapter
> クラスから作成されたオブジェクトのvalue値でエラーが発生していました。
作成されたオブジェクトはこちらもDataSetですか?Value値というのはどのように取得していますか?


> Value値に「型 'Oracle.DataAccess.Types.OracleNullValueException' の例外をスローしました。」
> というエラーメッセージが出力され、Value直下のbaseに
> "NULLデータの処理が無効です。"と出力されます。
>
> [質問]
> http://otndnld.oracle.co.jp/document/products/oracle10g/102/windows/B31247-01/OracleNullValueExceptionClass.htm
>
> こちらを見た限りこのエラーは、「NULL値が含まれるODP.NETタイプ構造にアクセスを試みたときに表示される例外」との
> ことですが、OracleDataAdapterクラスから作成されたオブジェクトの値にはNULLを格納してはいけないということなのでしょうか?
nullが入っているときに構造体へのアクセスをしてはいけないという事なので構造体へアクセスする前にNullであるかチェックする必要が
あります。
DataRow.IsNull(項目名)
でその項目がNullであるかチェック出来ます。


引用返信 編集キー/
■55730 / inTopicNo.3)  Re[1]: プロシージャの戻り値がnullの時
□投稿者/ やじゅ (1788回)-(2010/12/11(Sat) 01:33:21)
やじゅ さんの Web サイト
No55721 (ペンギン さん) に返信
> 開発ツール :VisualStudio2010
> 開発言語 :C#
> ミドルウェア:.NetFrameWork4.0
> Oracle.DataAccess.Client.OracleDataAdapterクラスから作成されたオブジェクトの値を
> Hashtableに格納し、それをString型の変数に格納して文字列を画面に表示しています。
> この時、戻り値がnullだと画面に「NULL」と表示されてしまいます。

.NET4.0を使えるなら、DataRowから値を取っている場合、Field<T>を使って変換してみるとか
例 Name = product.Field<string>("Name")

[.NET] DataRow から値を取り出すときって、DBNull かどうかチェックしてからキャスト… 面倒だよぉ
http://bluewatersoft.cocolog-nifty.com/blog/2010/08/net-datarow-dbn.html
引用返信 編集キー/
■55731 / inTopicNo.4)  Re[2]: プロシージャの戻り値がnullの時
□投稿者/ かたぎり (45回)-(2010/12/11(Sat) 08:10:55)
NULLが発生するフィールドが明確なら、SQLプロシジャ側で変換して渡す方法もあるかと思います。
たくさんあると面倒かもしれませんけど。

NVL(フィールド、'')で渡してしまえば、受け取り側はisDBNull関数不要なのでは?


引用返信 編集キー/
■55736 / inTopicNo.5)  Re[2]: プロシージャの戻り値がnullの時
□投稿者/ shu (276回)-(2010/12/11(Sat) 22:20:45)
No55730 (やじゅ さん) に返信

> .NET4.0を使えるなら、DataRowから値を取っている場合、Field<T>を使って変換してみるとか
> 例 Name = product.Field<string>("Name")
こんなものが実装されていたんですね。私は昔Accessを使っていた経緯からNz関数を実装して
使っていました。Extensionが使えるようになってからは以下の実装にしてます。(VB.NETでごめんなさい)
DataReaderでも似た実装をしています。


Imports System.Runtime.CompilerServices
Imports System.Data

Public Module 〜

<Extension>Public Function Nz(of T)(Row as DataRow, ColNm as String, NullValue as T) as T
    if Row.IsNull(ColNm) then
        return NullValue
    else
        return DirectCast(Row(ColNm), T)
    end if
End Function

'--- DateはNullのときNothingとすることが多いので別で定義
<Extension>Public Function NzDate(Row as DataRow, ColNm as String) as Date   
    if Row.IsNull(ColNm) then
        return Nothing
    else
        return DirectCast(Row(ColNm), Date)
    end if
End Function

End Module


使用するとき:
Dim row as Datarow
row = 〜

Dim a as String = row.Nz("文字列項目","")  '--- 型推論でNz(of String)に勝手になる
Dim b as Integer = row.Nz("Int項目", 0)      '--- 型推論でNz(of Integer)に勝手になる
Dim c as Decimal = row.Nz("Dec項目", 0D)     '--- 型推論でNz(of Decimal)に勝手になる
Dim d as Date = row.NzDate("Date項目")


引用返信 編集キー/
■55753 / inTopicNo.6)  Re[3]: プロシージャの戻り値がnullの時
□投稿者/ ペンギン (2回)-(2010/12/13(Mon) 13:59:40)
皆様ご回答ありがとうございます。

>ここで言うオブジェクトというのはDataSetですか?
ここで言うオブジェクトとは
protected OracleDataAdapter DA;
のように宣言した、OracleDataAdapter型のDAというオブジェクトのことです。

>どのように処理を行っていますか?



1)下記のSetReturn関数を実行して、Oracle内部に定義されたプロシージャの
 戻り値をハッシュに格納します。
2)下記のGetRetern関数を実行してハッシュ内にある戻り値を取得します。

3)取得した値に対し、toStringメソッドでString型に変換すると、nullのデータが文字列"null"になります。

-------------------------------------------------------
 protected ArrayList ARR_PRM = null;
 protected Hashtable HASH_RET = null;

 public override void SetReturn(IDbDataAdapter DA) {
    for (Int32 i = 0; i < ARR_PRM.Count; i++) {
     Param tmpPrm = (Param)ARR_PRM[i];
   HASH_RET.Add(tmpPrm.Name,((OracleDataAdapter)DA).SelectCommand.Parameters[i].Value);
   }
 }

 public override System.Object GetRetern(String key) {
 if (!HASH_RET.Contains(key)) {
 return null;
 }
 return HASH_RET[key];
 }
-------------------------------------------------------

>作成されたオブジェクトはこちらもDataSetですか?

作成されたオブジェクトは、DataSetではなく、最初の質問で答えたDAというオブジェクトのことです。
DAをVisualStudioのクイックウォッチ機能で確認すると、Valueの値が{null}となっています。
また、直下のbaseに"NULLデータの処理が無効です"というエラーメッセージが表示されています。

>Value値というのはどのように取得していますか?

2)上記GetReternを呼び出し、取得しています。

ご紹介していただいた、DataRow.IsNull(項目名)ですが、上記のようなソースでの使用方法が
よくわからないので教えていただけないでしょうか。

>NULLが発生するフィールドが明確なら、SQLプロシジャ側で変換して渡す方法もあるかと思います。
たくさんあるので今回はC#側の対応をします。

今回のようにOracleDataAdapter型のオブジェクトを使用してデータ取得してくる際は、
戻り値がnullにならないようにPL/SQL側で制御を入れなければならないのでしょうか?

よろしくお願いします。
引用返信 編集キー/
■55754 / inTopicNo.7)  Re[4]: プロシージャの戻り値がnullの時
□投稿者/ shu (280回)-(2010/12/13(Mon) 14:23:49)
2010/12/13(Mon) 14:46:46 編集(投稿者)

No55753 (ペンギン さん) に返信

DataAdapterはFillでDataTableまたはDataSetへデータを読込み
Updateで変更を反映させるためのものです。

> HASH_RET.Add(tmpPrm.Name,((OracleDataAdapter)DA).SelectCommand.Parameters[i].Value);
これでDBから値を取得したいのだと思いますが、このParametersはSelectCommandに対して
渡すパラメータになるので取得は出来ないかと思います。

OracleCommandを使用してExecuteをしてからParameterを取得すると良いのではないでしょうか?

取得した値がNullであるか確認するのに
DBNull.Value == 〜
と判断することが出来るらしい。(C#普段使っていない為未確認)

また
> protected ArrayList ARR_PRM = null;
ですが
protected List<Param> ARR_PRM = null;
を使用した方がいいかと思います。


引用返信 編集キー/
■55758 / inTopicNo.8)  Re[5]: プロシージャの戻り値がnullの時
□投稿者/ ペンギン (3回)-(2010/12/13(Mon) 16:04:30)
ご回答ありがとうございます。

>> HASH_RET.Add(tmpPrm.Name,((OracleDataAdapter)DA).SelectCommand.Parameters[i].Value);
>これでDBから値を取得したいのだと思いますが、このParametersはSelectCommandに対して
>渡すパラメータになるので取得は出来ないかと思います。

現在、以下の処理を実施し、PL/SQLをコールしています。
((OracleCommand)(DA.SelectCommand)).ExecuteNonQuery();

コールしたPL/SQLの戻り値はこれまでご説明した処理で取得しています。
これら一連の処理でnull以外の戻り値の取得は出来ています。
大変申し訳ございませんが、頂いた処理を良く理解しておりません。
何か参考になるドキュメントなどがございましたらご紹介お願い出来ますでしょうか。


>取得した値がNullであるか確認するのに
>DBNull.Value == 〜
>と判断することが出来るらしい。(C#普段使っていない為未確認)

以下のように改修してみましたがやはりnullと判断されず、elseとなってしまいます。
 if (DBNull.Value == (((OracleDataAdapter)DA).SelectCommand.Parameters[i].Value)){
  HASH_RET.Add(tmpPrm.Name,"");
 }else{
  HASH_RET.Add(tmpPrm.Name,((OracleDataAdapter)DA).SelectCommand.Parameters[i].Value);
 }

なお説明が不十分で大変申し訳ございませんが、実は今回の問題はシステムのWindows7対応で
ミドルウェアのバージョンアップに伴う改修を行っている際に発生したものです。
以前の環境では正常に動作しています。

[以前の環境]
  開発ツール :VisualStudio2003
   開発言語 :C#
   ミドルウェア :.NetFrameWork1.1
Oracle :OracleDatabase 9.2.0.8
     Oracle Client 9.2.0.8
     Oracle Data Provider for .NET 9.2.0.4.0
     Oracle Provider for OLE DB 9.2.0.4.0

情報が足りなければ補足します。
どうぞよろしくお願いします。
引用返信 編集キー/
■55759 / inTopicNo.9)  Re[6]: プロシージャの戻り値がnullの時
□投稿者/ shu (281回)-(2010/12/13(Mon) 16:27:31)
No55758 (ペンギン さん) に返信

> 現在、以下の処理を実施し、PL/SQLをコールしています。
> ((OracleCommand)(DA.SelectCommand)).ExecuteNonQuery();
これだとDAいらないです。
OracleCommandだけで処理出来ます。

> 以下のように改修してみましたがやはりnullと判断されず、elseとなってしまいます。
>  if (DBNull.Value == (((OracleDataAdapter)DA).SelectCommand.Parameters[i].Value)){
>   HASH_RET.Add(tmpPrm.Name,"");
>  }else{
>   HASH_RET.Add(tmpPrm.Name,((OracleDataAdapter)DA).SelectCommand.Parameters[i].Value);
>  }
Parameters[i].Valueがnull(オブジェクトとして)が入っているのであれば == nullでチェックはどうでしょう?


引用返信 編集キー/
■55813 / inTopicNo.10)  Re[7]: プロシージャの戻り値がnullの時
□投稿者/ ペンギン (4回)-(2010/12/15(Wed) 08:35:38)
ご回答ありがとうございます。

本件ですが、OracleParameter クラスのStatus
プロパティを確認する事で値がNullであるかを判断することが出来ました。

-----------------------------------------------
if (((OracleDataAdapter)DA).SelectCommand.Parameters[i].Status == OracleParameterStatus.NullFetched)
{
HASH_RET.Add(tmpPrm.Name, "");
Console.WriteLine("値がnull");
}
else
{
HASH_RET.Add(tmpPrm.Name, ((OracleDataAdapter)DA).SelectCommand.Parameters[i].Value);
Console.WriteLine("値がnullでない");
}
-----------------------------------------------

ご回答して頂いた方々、どうもありがとうございました。
解決済み
引用返信 編集キー/
■55814 / inTopicNo.11)  Re[8]: プロシージャの戻り値がnullの時
□投稿者/ shu (289回)-(2010/12/15(Wed) 09:03:04)
No55813 (ペンギン さん) に返信
> ご回答ありがとうございます。
>
> 本件ですが、OracleParameter クラスのStatus
> プロパティを確認する事で値がNullであるかを判断することが出来ました。
OracleParameterはStatusを見ないと分からないのですね。



再度書きますが、DataAdapterなしでOracleCommandとOracleConnectionだけで
今回の処理は出来ますよ。


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


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

このトピックに書きこむ

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

管理者用

- Child Tree -