アプリ版:「スタンプのみでお礼する」機能のリリースについて

こんばんわ。

C#のフォームのテキストボックスに[社員番号]を入力し、社員マスタから該当社員氏名を同じフォーム内のラベルに表示するという処理を行おうとしています。
以下のコードで、
[goButton]を押したあと、社員マスタの氏名をラベルに表示する部分の記述の仕方がわかりません。

社員マスタは[syainNo]と[simei]という2列のフィールドで構成されています。

private void Form1_Load(object sender, System.EventArgs e)
{
dataSet11.Clear();
sqldataAdapter1.Fill(dataSet11, "syainM");
}

private void goButton_Click(object sender, System.EventArgs e)
{
int i; //カウンタ


//検索する値が入力されていないとき
if (textBox1.Text == "")
{

MessageBox.Show("検索する社員番号を入力してください");
return;

}

//先頭から検索
for (i = 0; i < dataSet11.Tables["syainM"].Rows.Count; i++)
{
if ( dataSet11.Tables["syainM"].Rows[i]["syainNo"].ToString() == textBox1.Text)
{

//ここでラベルに社員マスタの氏名を表示する

return;

}
}

}
どなたかわかる方よろしくお願いします。

A 回答 (6件)

そうですね。

データセットですと更新して実際にデーターベースに書き戻す際に、自分が取ってきた時と変わってないか(誰かが書き換えた)を確かめてから書き戻す必要があります。特に、合計などのように加算されていくものは要注意です。

それから、for文でまわすのは効率が悪いので、できるだけやらない方が良いです。

さて、i=0ですが、実際に示されたコードで確かめましたが、問題なく動きました。
for (i = 0; i < dataSet11.Tables["syainM"].Rows.Count; i++)
だとだめで、
for (i = 1; i < dataSet11.Tables["syainM"].Rows.Count; i++)
だと良いってことですよね?う~ん、なぜでしょう?その謎を知りたくなっちゃいました(^^;

この回答への補足

遅くなり失礼しました。
更に、補足でのお礼で失礼します。

やはり、i=0だとうまく動かないんで悩み続けていました。(半分、諦めていたとも・・・(^_^;)
No.5で教えていただいたコードを記述し実行してみたら、すんなり問題なく動作しました。

本当はもっとしっかりと押さえていかなければなりませんが、今回はこのコードを使わせていただこうと思います。

ありがとうございました。
プログラムって難しいですねぇ~。
でも、完成まで頑張ってみます。また何かの際に回答を付けていただけると幸いです。

補足日時:2004/10/13 11:38
    • good
    • 0
この回答へのお礼

ありがとうございます。

hppさんが実行してできたということは、僕の設計で何か問題があるのでしょうね。
もう一度、一から作り直して動かしてみます。
結果はまたご報告させていただきます。

それと、データセットを使った更新の際には、書き戻すテーブルの変化も確認しなくちゃいけないのですね。
今回の質問は最終的に作ろうとしているものの部品ですので、まだまだ問題が起きそうです(^^;)

お礼日時:2004/10/06 23:55

>ところで、このように直接データにアクセスするということは、何か利点があるのでしょうか?


>データセットを使い処理する方法と比べ、どんな利点・欠点があるのか不思議に思ったもので。

データセットはデータベースからデータを取ってきて、クライアントのメモリー上にコピーしてテーブルを作っています。つまり、データベースとこの時点で切り離されています。
もし、マルチユーザー環境で、誰かが社員マスタのデータを変更したとしても、それはデータセットには反映されません。もっとも今回のケースは検索する直前でデータセットを作っているので、そういった可能性は少ないですが。
また、データが巨大になればそのデータを全てとってこなくてはならなくなり、処理時間の増大につながります。当然、巨大になればforでまわせば検索時間もかかります。
では、なぜデータセットがあるかといえば、インターネットなどのセッションを継続できない場合や、そうではなくても都合が良い場合があるからです。このあたりはいろいろと解説されていると思います。

今回の場合は単純な検索ですので、わざわざローカルにデータをコピーしてデータセットを作り、そこから検索するより、直接データベースに検索させて結果だけを受け取った方がスマートでしょう。

どうしてもデータセットということになれば、せめてfor文はやめて、selectを使った方がパフォーマンスが良いように思えます。

System.Data.DataRow [] dtrows = dataSet1.Tables["syainM"].Select("syainNo=" + textBox1.Text);

if (dtrows.Length > 0)
  label1.Text = dtrows[0]["simei"].ToString();
else
  label1.Text = "(該当なし)";

i=0からだとうまくいかないのは不思議ですね。よろしければコードを載せてください。
    • good
    • 0
この回答へのお礼

こんばんわ。
再び回答ありがとうございます。

接続のタイミングの問題なのですね。
データセットの場合、接続を維持しないというのは読んでいたので、常に使っていました。
データベースに接続する回数を増やすことが、どのような状況を生み出すか少々不安に思っていました。(同時接続の際に、ロック等起こらないのか)
データベースの知識も欠如しているせいですね。(^^;)

for文だと、1レコードずつということで時間がかかるのですよね?
select文だと時間が軽減されるのですね。
コードの方も試してみます。

うまくいかないコードは、質問文の
「//ここでラベルに社員マスタの氏名を表示する」のあとに、gimmickさんに教えていただいた「label1.Text = dataSet11.Tables["syainM"].Rows[i]["simei"].ToString(); 」とし、
for文のiの初期値を1としています。

何かお気づきの点がありましたら、よろしくお願いします。

お礼日時:2004/10/06 21:32

すみません。

hppです。以下の方がスマートですね。

sqlConnection1.Open();

sqlCommand1.CommandText = "select simei from syainM where syainNo=" + textBox1.Text;

object kekka = sqlCommand1.ExecuteScalar();

if (kekka != null)
  label1.Text = kekka.ToString();
else
  label1.Text = "(該当なし)";

sqlConnection1.Close();

※sqlConnection1のConnectionString、およびsqlCommand1のconnectionにsqlConnection1がプロパティで設定してあるものとします。
※コードを見やすくするため、頭の半角は全角に変えてあります。本当はtabだけど。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

2つ回答していただきましたが、お礼はこちらにまとめさせていただきます。

どこかにある落とし穴にはまっているんだとは思うのですが、
なかなか解きほぐせないでいます。
i=0の時から、処理したいです。。(^^;)

質問したコードは部品として使うもので、別個にテストしていましたが、
実際に使いたいプロジェクトに組み込んでみたら、
今度は別の問題が発生し・・・とどつぼにはまるコースっぽいです。
しばらく安眠できないな・・・

回答に載せていただいたコードを見させてもらいました。
これは、プログラムから直接アクセスするタイプの書き方ですよね?
SQLを使って処理するには、このようにやるんですね。
まだ、本を見ながらデータセット作って・・・とやっている段階ですので、
このようなスマートな書き方をできるようになるのは、まだ先の話になりそうです。

ところで、このように直接データにアクセスするということは、何か利点があるのでしょうか?
データセットを使い処理する方法と比べ、どんな利点・欠点があるのか不思議に思ったもので。

お礼日時:2004/10/06 11:21

特にコードは間違っていないと思うのですが・・・。

何か他に落とし穴があると思います。
それはそうとして、普通は以下のようにコーディングすると思います。

sqlConnection1.Open();

sqlCommand1.CommandText = "select simei from syainM where syainNo=" + textBox1.Text;

object kekka = sqlCommand1.ExecuteScalar();

if (kekka != null)
  label1.Text = sqlCommand1.ExecuteScalar().ToString();
else
  label1.Text = "(該当なし)";

sqlConnection1.Close();

※sqlConnection1のConnectionString、およびsqlCommand1のconnectionにsqlConnection1がプロパティで設定してあるものとします。
※コードを見やすくするため、頭の半角は全角に変えてあります。本当はtabだけど。
    • good
    • 0

それでは、ループ部分の処理をデバッガで確認したらどうですか?



 データセットに正しくデータが格納されているのか?
 if文でどのような文字列を比較しているのか?

等を確認すれば解決すると思いますよ。
    • good
    • 0
この回答へのお礼

再び回答ありがとうございます。

ブレークポイントを設定して確認してみました。
変数iが初期値”0”のままであるためでした。
その後他の部分も確認してみましたが、
if条件式の箇所でデータセットの[syainNo]部分と比較していないようです。
textBox1.Textには、テキストボックスで入力した社員Noを保持していました。
ちなみにデータセットは、データグリッドに表示させてみましたが、中身は想定したものが入っていました。

そして、あれこれいじっているうちに、変数iを1以上にすると、希望の動作になることがわかりました。
でも、データセットの行は”0”から始まっていたはずですよね?
ということは、上で書いた「比較していないのでは?」という予想も外れていたことに・・・
こうなると更に謎が・・・

うむぅ。やはりExcelのVlookUp関数みたいに簡単にはいかないものですね。

お礼日時:2004/10/06 08:43

質問のコードを見る限りでは以下のようにすればよいと思いますが…。


何を悩んでいるのかがよくわかりません。

label1.Text = dataSet11.Tables["syainM"].Rows[i]["simei"];
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

gimmickさんの書かれているコードを動かしてみました。
そうしますと、初期状態でラベルに表示されている社員氏名から変更せずに困っていました。
[社員番号] [氏名]
 1000     Aさん
 1001     Bさん

フォームロード時にテキストボックスには「1000」、ラベルには「Aさん」が表示されています。
その後、テキストボックスに「1001」と入力し、Enterまたは、goButtonをクリックすると、ラベルが「Bさん」に変更される
というものを作っていて、クリック後の変化が起きない(Aさんのままである)ことに困っていました。

そこで、上記質問となったということです。

個人的には、goButtonを押すごとにテキストボックスの値と同じレコードを検索するループに入り、合致したインデックス番号を取得しなおすので、ラベルに表示されるものは変化が起きると考えて作っていたのですが・・・

お礼日時:2004/10/06 06:14

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!