- PR -

DataGridでオーバフローが発生する

1
投稿者投稿内容
ゆきお
常連さん
会議室デビュー日: 2003/12/17
投稿数: 22
お住まい・勤務地: 名古屋市
投稿日時: 2004-01-20 11:02
こんにちは。ゆきおといいます。

Oracleのデータディクショナリを検索するシステムをC#で作成しています。
DataGridに結果を格納させているのですが、特定のSQL文を発行するとオーバー
フローが発生しDataGridに結果が格納されません。

【環境】
OS:Windows2000 SP4
Oracle:Oracle9i Release 9.2.0 トライアル版
言語:Visual C#.NET + Oracle Data Provider for .NET(ODP.NET)
.Net Framework v1.1

【ソースコード】

class ConnectOracleDB
{
  [STAThread]
  static void Main()
  {
    Application.Run(new Form1());
}
}
 
private void button1_Click(object sender, System.EventArgs e)
{
// @Oracleに接続
// Create the connect object
OracleConnection con = new OracleConnection();
con.ConnectionString = "User Id=xxxx;Password=pppp; Data Source=dddd;
DBA Privilege=SYSDBA;";

  // Instantiate OracleDataAdapter to create DataSet
  OracleDataAdapter myAdapter = new OracleDataAdapter();

// Fetch Product Details
myAdapter.SelectCommand = new OracleCommand
("SELECT namespace,gethitratio FROM v$librarycache",con);

// DataTable
myDataTable = new DataTable();
myAdapter.Fill(myDataTable);

// ADataGridに結果格納
  dataGrid1.SetDataBinding(myDataTable);
}

【上記APを実行するとエラーとなる症状】
1.画面でボタン(button1)をクリックすると以下のメッセージが表示される。
 
 「演算操作の結果オーバーフローが発生しました。」

2.DataGridにはNullが表示される

【問題となるSQL文】

SELECT namespace,gethitratio FROM v$librarycache

【SQL/Plusの結果】

NAMESPACE GETHITRATIO
--------------- -----------
SQL AREA .992936844 ・・・・ A
TABLE/PROCEDURE .990651713
BODY .947368421
TRIGGER .966666667
INDEX .997985515
CLUSTER .959302326
OBJECT 1
PIPE 1
JAVA SOURCE 1
JAVA RESOURCE 1
JAVA DATA 1

【質問事項】
SQL/Plusの結果よりSQL文に間違いはないと考えています。また他の
SQL文を発行すると(例:SELECT * FROM v$database)正常に結果が表
示されることよりDataGridに原因があると自分では考えています。
 具体的には「結果」よりGETHITRATIO列の小数点(1以外の結果)
がDataGridでは表示できないのかなと考えています。

 質問ですが
  ・オーバフローの原因は上記であっているんでしょうか?
  ・またこのようなオーバーフローする事象はDataGridでは
   よくあるのでしょうか?

 どなたかすいませんが教えていただけると幸いです。

 ※長文で申し訳ありません。
ゆうじゅん
ぬし
会議室デビュー日: 2004/01/16
投稿数: 347
投稿日時: 2004-01-20 11:38
>// ADataGridに結果格納
>  dataGrid1.SetDataBinding(myDataTable);

この行をコメントアウトにしたらどうなります?

>myAdapter.Fill(myDataTable);
こっちでエラーがでてるかもしれないので
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-01-20 12:03
「OCI-22053:オーバーフロー・エラー」でしょうか?
Adapter.Fillで発生しています。
NAL-6295
ぬし
会議室デビュー日: 2003/01/26
投稿数: 966
お住まい・勤務地: 東京
投稿日時: 2004-01-20 12:58
・OracleNumber 構造体
http://www.microsoft.com/japan/msdn/library/ja/cpref/html/frlrfsystemdataoracleclientoraclenumberclasstopic.asp?frame=true

この情報が参考にならないでしょうか?
外していたらすいません。
ゆきお
常連さん
会議室デビュー日: 2003/12/17
投稿数: 22
お住まい・勤務地: 名古屋市
投稿日時: 2004-01-20 14:33
引用:

ゆうじゅんさんの書き込み (2004-01-20 11:38) より:
>// ADataGridに結果格納
>  dataGrid1.SetDataBinding(myDataTable);

この行をコメントアウトにしたらどうなります?

>myAdapter.Fill(myDataTable);
こっちでエラーがでてるかもしれないので




ゆうじゅんさんこんにちは。返信ありがとうございます。
コメントアウトしてデバッグモードで実行してみました。

ご指摘通りmyAdapter.Fill(myDataTable); で例外が発生しました。
メッセージを記します。

↓-----------------------------------------------------------------------------
'System.OverflowException'のハンドルされていない例外が oracle.dataaccess.dll で
発生しました。

追加情報:演算操作の結果オーバフローが発生しました。
↑-----------------------------------------------------------------------------

これでいくとdataGridが原因ではなくてmyAdapter.Fillに原因がありそうです。
ますますわからなくなってきたような。


引用:

「OCI-22053:オーバーフロー・エラー」でしょうか?
Adapter.Fillで発生しています。



Jittaさんこんにちは。続けざまの返信で失礼します。
上記のOCIのエラーメッセージは表示されませんでした。ただAdapter.Fillが原因のようですね。ただどうすればいいのか考え中です。
(OracleDataAdapter myAdapterとAdapterは一緒と考えていいのでしょうか?)
ゆきお
常連さん
会議室デビュー日: 2003/12/17
投稿数: 22
お住まい・勤務地: 名古屋市
投稿日時: 2004-01-20 16:21
NAL-6295さん。こんにちは。

OracleNumber 構造体参照させていただきました。
大きなデータを取得する場合getOracleNumberを使用するようですね。

OracleDataReader reader = cmd.ExecuteReader();

reader.GetOracleNumber(1);

情報参考になります。原因としては今のところ myAdapter.Fill(myDataTable);
で発生してるようなので回避策をいろいろと探します。情報ありがとうございます。
NAL-6295
ぬし
会議室デビュー日: 2003/01/26
投稿数: 966
お住まい・勤務地: 東京
投稿日時: 2004-01-20 16:35
引用:

ゆきおさんの書き込み (2004-01-20 16:21) より:
NAL-6295さん。こんにちは。

OracleNumber 構造体参照させていただきました。
大きなデータを取得する場合getOracleNumberを使用するようですね。

OracleDataReader reader = cmd.ExecuteReader();

reader.GetOracleNumber(1);

情報参考になります。原因としては今のところ myAdapter.Fill(myDataTable);
で発生してるようなので回避策をいろいろと探します。情報ありがとうございます。




http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpguide/html/cpconmappingnetdataproviderdatatypestonetframeworkdatatypes.asp
の下の方の説明によると・・・

FillErrorイベントで回避できるようです。

で、回避の仕方は

http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpguide/html/cpconaddingremovingadonetproviderevents.asp

のFillErrorの項に掲載されています。

以上、よろしくお願いします。
ゆきお
常連さん
会議室デビュー日: 2003/12/17
投稿数: 22
お住まい・勤務地: 名古屋市
投稿日時: 2004-01-21 11:33
NAL-6295さんこんにちは。

引用:

FillErrorイベントで回避できるようです。


FillErrorイベントを作成して、実行したらエラーは回避できるようになりました。

以下を追加してみました。
 @イベントハンドラの作成
  myAdapter.FillError += new FillErrorEventHandler(FillError);
 Aエラー処理のメソッド作成
  protected static void FillError(object sender, FillErrorEventArgs args)

最後にソースコードを記しますが、処理としてはFillを実行した後にオーバフローが発生するとイベントを発生させ、メソッド「FillError」を実行させます。FillErrorの中でオーバーフローが発生した列に対し、「null」文字列を埋め込みます。今回はサンプルに掲示されたイメージで動作させています。

引用:

http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpguide/html/cpconmappingnetdataproviderdatatypestonetframeworkdatatypes.asp
の下の方の説明によると・・・


上記記事から考えると、Oracleのデータ型と.NET Framework 型での相違に問題がありそうなのでオーバフローの発生した列に対して個別に「reader.GetOracleNumber(1) 」を発行し@個別に列の値を取得、ADataTableにデータ格納、BDataGridに表示といった処理が必要なのかなという気がします。@〜Bについては時間がかかると思いますが、挑戦しようと考えています。
NAL-6295さん貴重な情報どうもありがとうございます。また返信していただいた方にも本問題に取り組む上で大変助かりました。

【現ソースコード】
private void button1_Click(object sender, System.EventArgs e)
{
  // Oracleに接続
  // Create the connect object
  string connectionString = "User Id=sys;Password=sys; Data Source=test; DBA Privilege=SYSDBA;";
  con = new OracleConnection(connectionString);
  con.Open();

  string cmdQuery = "SELECT namespace,gethitratio FROM v$librarycache";

  // Instantiate OracleDataAdapter to create DataSet
  myAdapter = new OracleDataAdapter();

  *** 追加@ イベントハンドラの作成 ***
  myAdapter.FillError += new FillErrorEventHandler(FillError);

  // Fetch Product Details
  myAdapter.SelectCommand = new OracleCommand(cmdQuery ,con);

  // DataTable方式
  myDataTable = new DataTable();
  myAdapter.Fill(myDataTable);

  // DataGridに結果格納
  this.dataGrid1.SetDataBinding(myDataTable,"");
}

*** 追加A ***
protected static void FillError(object sender, FillErrorEventArgs args)
{
  if (args.Errors.GetType() == typeof(System.OverflowException))
{
  // Code to handle precision loss.
  //Add a row to table using the values from the first two columns.
  DataRow myRow = args.DataTable.Rows.Add(new object[] {args.Value[0],DBNull.Value});
//Set the RowError containing the value for the third column.
  //args.RowError = "OverflowException Encountered. Value from data source: " + args.Values[1];

  args.Continue = true;
}
1

スキルアップ/キャリアアップ(JOB@IT)