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

オブジェクト参照がオブジェクト インスタンスに設定されていません。

はじめまして、高中と申します。現在、.NET及びC#にてwebアプリケーションを開発中の者です。
データグリッド内のプッシュボタンをクリックすると,"オブジェクト参照がオブジェクト インスタンスに設定されていません",というエラーメッセージが出力されて処理が中断してしまいます。

以下がそのソースです。

namespace test3
{
///
/// WebForm1 の概要の説明です。
///
public class WebForm1 : System.Web.UI.Page
{
protected System.Data.DataSet dataSet1;
protected System.Data.DataSet EntryEria;

    private void Page_Load(object sender, System.EventArgs e)
    {
        // ページを初期化するユーザー コードをここに挿入します。
        if (!IsPostBack)
        {
            //  マスタを読み込む
            oracleDataAdapter1.Fill(dataSet1);

する
OriginalData = dataSet1.Copy();
EntryEria = dataSet1.Clone();
EntryEria.Tables[0].Rows.InsertAt(EntryEria.Tables[0].NewRow(), 0);
// 更新用,登録用データセットをバインドする
DataGrid1.DataSource=EntryEria;
DataGrid1.DataBind();
DataGrid2.DataSource=dataSet1;
DataGrid2.DataBind();
Session["x"] = dataSet1;
Session["z"] = EntryEria;
}
}

    public void DataGrid2_ItemCommand(object sender, DataGridCommandEventArgs  e)
    {
        dataSet1.Merge((DataSet)Session["x"]);
        EntryEria.Merge((DataSet)Session["z"]); <-- この行でエラー
        if (e.CommandName == "Delete")
        {
            //  処理が入る
        }           

    }

}

}

同じようにsession変数にセットし、同じようにマージしているにもかかわらず、

dataSet1.Merge((DataSet)Session["x"]);

はエラーにならず、

EntryEria.Merge((DataSet)Session["z"]);

はエラーになります。

初歩的な事だと思うのですが昨日はまる一日この件で仕事になりませんでした。
どなたか原因をご存知の方は教えていただけないでしょうか?

質問者:高中

回答

こんにちは。

何が null になっているのかデバッガできっちり確認されましたか?
DataSet.Clone() のヘルプをしっかり読んでみて下さい。今回の例外の原因が書かれています。
________________<a href="http://blogs.wankuma.com/shuujin/" target="blank">囚人のジレンマな日々

投稿者:囚人

編集 履歴 (0)

 囚人さん、ありがとうございました。デバッガで確認したところ、EntryEriaが未定義となっていました。DataSet.Clone()を再度実行すると、とりあえずエラーで落ちることはなくなりました。(原因に関してはまだ理解できていません)

 現在私は周りにC#の経験者がおらず、MSDNも手に入らないという環境で開発を行っています。(私は一週間前に.NET及びC#を始めたばかりで、WEBアプリケーションもオブジェクト指向プログラムの経験もありません)

 今後ともよろしくお願いします。

投稿者:高中

編集 履歴 (0)

なるほど。失礼しました。

とりあえず
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/netstart/html/cpframeworkref_start.asp
で、リファレンスは参照できます。

一応 DataSet.Clone() はこちらです。
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpref/html/frlrfsystemdatadatasetclassclonetopic.asp

デバッガは使える環境みたいですが、開発は何を使っていますか?
現状は本を読みながらの学習といったところでしょうか?

今回の件の結論を言いますと、Clone() はデータまでコピーされないって事です。

それでは、一緒に頑張っていきましょう。

________________<a href="http://blogs.wankuma.com/shuujin/" target="blank">囚人のジレンマな日々

投稿者:囚人

編集 履歴 (0)

囚人さん、ご親切にどうもありがとうございます。
DataSet.Clone()がスキーマ等のコピーでデータそのものをコピーしないというのは理解できるのですが、私はClone()を実行した後、

EntryEria.Tables[0].Rows.InsertAt(EntryEria.Tables[0].NewRow(), 0);

として空白の行を一行挿入しています。このDataSetをセッション変数に保存しているのでマージすれば元通りになると考えているのですが、うまくいきませんでした(ココがわからないんです).

やりたいことは、このコピー元、コピー先二つのDataSetを共にバインドして、読み込んだデータを表示するグリッドと、空白行を一行だけ表示する登録用のグリットを表示してオペレータからキー入力された値をコピー元のDataSetに追加し,コピー元のグリッドを再バインドすればすれば追加行がコピー元のグリッドに再表示される、といった処理です。

ちなみに開発環境はWindows 2003 Saver
ツールはVisual Studio.NETを使っています。

投稿者:高中

編集 履歴 (0)

おーそっかそっか。すみません。見当違いのことを言ったみたいですね。



protected System.Data.DataSet dataSet1; 
protected System.Data.DataSet EntryEria; 

これのインスタンスはどこで作ってるんですかね?
DataSet を画面に貼るってあったんでしたっけ?(現在環境がなくて試せません)

インスタンスを作らないと、メソッドを呼ぶなんてできないので、
EntryEria.Merge()
ができないという事かな。

dataSet1 はどこでインスタンスを作っていますか?
________________<a href="http://blogs.wankuma.com/shuujin/" target="blank">囚人のジレンマな日々

投稿者:囚人

編集 履歴 (0)

インスタンスは明示的に生成していません。私の考えでは

oracleDataAdapter1.Fill(dataSet1);

とした時点と

EntryEria = dataSet1.Clone(); 

として時点で生成されていると思うのですが間違っていますか? 事実、このdataSet1をグリッドにセットしてバインドするとデータベースのデータがグリッドに表示されます。

投稿者:高中

編集 履歴 (0)

試せました。
DataSet を画面に貼って使うという方法をした事がなかったので、確認が遅れました。すみません。

dataSet1 は画面に貼っていますね?
InitializeComponent() でインスタンスが作られているようです。
oracleDataAdapter1.Fill() を行うときも、Fill() する前にインスタンスを作らなければなりません。

dataSet1.Clone();
で新しいインスタンスが作られるというは正解です。
しかしそれは、初回リクエスト時にしか行っていませんね。

つまり
public void DataGrid2_ItemCommand
では、EntryEria のインスタンスが作られていないのでしょう。

しかし、EntryEria もたぶん画面に貼っているので、インスタンスは作られているかもしれません。
しかし、その場合でもただインスタンスが作られただけの状態(Clone()されていないのでスキーマがない)なので、
Merge() ができない状況なのではないでしょうか。

________________<a href="http://blogs.wankuma.com/shuujin/" target="blank">囚人のジレンマな日々

投稿者:囚人

編集 履歴 (0)

まだよく理解できていないのですが、おそらく囚人さんの考えが正しいのでしょう。

>InitializeComponent() でインスタンスが作られているようです。
>oracleDataAdapter1.Fill() を行うときも、Fill() する前にインスタンスを作らなければなりません。

エディターで確認しました.

囚人さん、長々とありがとうございました.
私の現状は、グリッドからキー入力されたデータを取得するところまで扱ぎつけましたが、取得したデータをRows.AddでdataSet1に追加しようとしてエラー(この行は既に別のテーブルに属しています)でつかまっています。
手におえなくなったら又スレッドを立てますのでその時はよろしく。

投稿者:高中

編集 履歴 (0)

本題から外れますが。

protected System.Data.DataSet EntryEria;
やめましょうよ、英語とローマ字を混在させるのは。せめて、「Entryエリア」にしましょう?

投稿者:Jitta

編集 履歴 (0)

Jittaさんの書き込み (2005-12-10 22:50) より:

protected System.Data.DataSet EntryEria;

やめましょうよ、英語とローマ字を混在させるのは。せめて、「Entryエリア」にしましょう?

EntryArea じゃあダメなんでしょうかね?
Entry って言ってるんだから、カタカナ英語 (和製英語) はやめたいです。。。

________________C# と VB.NET の入門サイト
<a href="http://blogs.wankuma.com/jeanne/" target="
blank">じゃんぬねっと日誌

投稿者:じゃんぬねっと

編集 履歴 (0)

じゃんぬねっとさんの書き込み(2005-12-11 10:36)より:

EntryArea じゃあダメなんでしょうかね?

Entry って言ってるんだから、カタカナ英語 (和製英語) はやめたいです。。。

じゃんぬさんがいぢめるぅ〜(;.
 いや、同じです。同じなんですが、「area のスペルがわからない、というのはナシにしても、スペルがわからない名詞があるとか?」ということを考えて、

「英語の動詞」+「日本語の名詞」

を提案してみたり。。。

まぁ、そんな中途半端なことするより、R・田中一郎さんの『Function 数値だ(ByVal 文字列 As String)』のように、完全に日本語で作成するのもいいかも。

投稿者:Jitta

編集 履歴 (0)
ウォッチ

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