質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.37%

「ASP.NET WebAPI」 PostgresDBで取得したデータを変数に代入する際の疑問点

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 844

score 7

ASP.NET C#初学者です。
WebAPIを作成するために、ドキュメントに沿って学習しています。DBと連携しパラメータによって動的にデータを返すことを想定し、試しに単純なテストデータから任意のカラムデータを変数に代入する際にスコープの問題か変数への代入後の参照がうまくできず、フィールド変数で定義した場合は参照できましたが以下のコードの場所ではデバッグ実行できません。

開発環境(windows10, VisualStudio2015 Express for web, .NET Framework4.5.2)

テーブルデータは以下になります。

id name age
1 taro 19
2 tadokoro 24
using AnimalsAppFor_C.Models;
using Npgsql;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Web.Http;

namespace AnimalsApp.Controllers
{
    [RoutePrefix("api/animals")]
    public class AnimalsController : ApiController
    {
        //①フィールド変数で定義すると値が割り当てられる。
        string test;


        Animal[] products = new Animal[]
        {
            //今回は関係がないので省略。
        };


        [HttpGet]
        [Route("")]
        public IEnumerable<Animal> GetAllAnimals()
        {
            return products;
        }

        [HttpGet]
        [Route("{id}")]
        public IHttpActionResult GetAnimal(int id)
        {
            //接続文字列
            string conn_str = "Server=localhost;Port=5432;User ID=postgres;Database=postgres;Password=パスワード;Enlist=true";
      //②リストクラスを定義したtest_listは正常にretunされる。
            List<string> test_list = new List<string>();
            //↓③これだと未割当のローカル変数が使用されましたとでる。
            //string test;
            using (var conn = new NpgsqlConnection(conn_str))
            {
                //PostgreSQLへ接続
                conn.Open();
                Debug.WriteLine("Connection success!");
 
                var command = new NpgsqlCommand(@"select * from person", conn);
                //↓④これだと現在のコンテキストに'test'は存在しませんとでる。
                //string test;
                var dataReader = command.ExecuteReader();
                int i = 0;
                while (dataReader.Read())
                {
                    Debug.WriteLine("value : {0},", dataReader["name"]);
                    //配列ver
                    test_list.Add((string)dataReader["name"]);
                    //文字列ver
                    test = (string)dataReader["name"];
                    Debug.WriteLine(i + ":" +test);
                    i = i + 1;
                }
                conn.Close();
            }

            return Ok(test); 
            /*  ①の結果:"tadokoro"
               ③の結果:未割当のローカル変数が使用されましたとでる。デバック実行不可。
        ④の結果:現在のコンテキストに'test'は存在しませんとでる。デバック実行不可。
            */
       //return Ok(test_list ); >> ②結果:["taro","tadokoro"]
        }
    }
}


④の場合、スコープによる参照ができていない問題だと思うのですが、③の場合、②と同じ場所に定義していますが、②は参照され、③は未割り当てとなるのはなぜでしょうか?
そもそもwhile内に文字列として入れていることが不格好ですが、なぜ③のケースはダメなのか調べましたが思うような結果を得られず質問させていただきました。
何か参考になるサイトまたはご教授いただけないでしょうか?
お願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • SurferOnWww

    2021/04/09 21:39

    開発環境(OS, Visual Studio, .NET Framework のバージョンなど)を書いてください。

    ASP.NET のタグもつけてください。自分の都合で恐縮ですが ASP.NET Web API は見てないので。

    キャンセル

  • yt07

    2021/04/09 22:01

    失礼いたしました。
    環境環境、タグ付け追記しました。

    キャンセル

  • SurferOnWww

    2021/04/09 22:29

    ASP.NET Web API の質問ではなくて、ADO.NET + Npgsql を使った .NET Framework の C# アプリからの PostgreSQL への接続、SELECT クエリの実行、データの取得の問題のように見えます。ASP.NET Web API 関係なく、そこだけわかればいいのでしょうか?

    キャンセル

  • yt07

    2021/04/09 22:48

    切り分けができておらず申し訳ございません。
    今回は言っていただいたように、データ取得後のデータを変数に格納し、APIをたたいた結果を表示するにあたり、変数の定義の疑問について質問させていただきましたので、その部分だけわかれば大丈夫です。

    キャンセル

回答 1

checkベストアンサー

+2

表題に、

「ASP.NET WebAPI」 PostgresDBで取得したデータを変数に代入する際の疑問点

と書いてありましたが、「ASP.NET Web API」も「PostgresDB で取得」もこのスレッドの課題とは直接関係なくて、変数を宣言する場所、初期化(割り当て)、スコープの話で、string test; を宣言する場所を、

① クラスのフィールドとして宣言、または

③ メソッド内のローカル変数として宣言、または

④ メソッド内の using { } 内のローカル変数として宣言

と変えると、結果が変わるのは何故かという話ですよね。

④の場合、スコープによる参照ができていない問題だと思うのですが、

その通りです。using { } 内で宣言しているので、その { } 外では「現在のコンテキストに'test'は存在しません」となります。

③の場合、②と同じ場所に定義していますが、②は参照され、③は未割り当てとなるのはなぜでしょうか?

② は List<string> test_list = new List<string>(); となっており、変数 test_list 宣言だけでなく、new List<string>() によって List<string> 型のインスタンスが生成され、それへの参照が変数 test_list に代入されています。

一方、③ は string test; となっており、変数 test が宣言されているのみで、そこでは test が指す実体(インスタンス)がありません。while 文の中で代入されるようコーディングされていますが、コンパイラには実行時に while の条件が true になって (string)dataReader["name"] が代入されるかわ分からないのでエラーにしています。

③ のところで string test = null; としておけばエラーにはならないはずです。

そのあたりはエラーメッセージ「未割当のローカル変数が使用されました」ググるといろいろヒットするのでやってみてください。

なお、① の場合は string test; のままで自動的に null が使用されるようです。

イメージ説明

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2021/04/10 13:37

    ありがとうございます。
    疑問が解決しスッキリしました。
    ③string test = null;と既定値を割り当てることでエラーにならず思っているデータが表示されました。
    調べてみるとstring test = default(string);としてもエラーなく同様に表示されました。
    基礎的なところが理解できていませんでした。
    ありがとうございます。

    キャンセル

  • 2021/04/11 07:43 編集

    default(string) は null です。

    もし、null は使いたくないということがあれば、"" とか "仮" でもいいと思います。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る