ms アクセス - C# でテーブルにデータを挿入するのに問題があります

okwaves2024-01-25  7

private void btn_view_Click(object sender, EventArgs e)
{
        con.Open();

        OleDbDataAdapter da = new OleDbDataAdapter("Select * from tbl_emp", con);
        DataSet ds = new DataSet();
        da.Fill(ds);

        dgv_emptable.DataSource = ds.Tables[0];

        con.Close();
}

private void btn_insert_Click(object sender, EventArgs e)
{
        con.Open();

        OleDbCommand cmd = new OleDbCommand();

        cmd.CommandText = "Insert into tbl_emp(emp_id,emp_name,emp_surname,designation_id,dept_id) Values(" + txt_id.Text + " , '" + txt_name.Text + "','" + txt_phone.Text + "'," + cmb_desigid.SelectedValue + ",'" + cmb_deptid.SelectedValue.ToString() +"')"; 
        cmd.Connection = con;
        cmd.ExecuteNonQuery();
        MessageBox.Show("Record inserted");
        con.Close();
}

private void Form1_Load(object sender, EventArgs e)
{
    con.Open();

    OleDbDataAdapter da = new OleDbDataAdapter("Select * from tbl_designation", con);

    DataSet ds = new DataSet();
    da.Fill(ds);

    cmb_desigid.DataSource = ds.Tables[0];
    cmb_desigid.DisplayMember = "designation_type";
    cmb_desigid.ValueMember = "designation_id";

    con.Close();

    con.Open();

    OleDbDataAdapter db = new OleDbDataAdapter("Select * from tbl_dept",con);

    DataSet dm = new DataSet();
    db.Fill(dm);

    cmb_deptid.DataSource = dm.Tables[0];
    cmb_deptid.DisplayMember = "dept_name";
    cmb_deptid.ValueMember = "dept_id";

    con.Close();
}

データベースをバインドし、テーブルにデータを挿入する挿入クエリを作成していますが、cmd.ExecuteNonQuery で同じエラーが発生します

必須パラメータに指定されたパラメータがありません。

徹底的にチェックしましたが、エラーが見つからないようです

emp_id、emmp_name、emp_surname にはテキストボックスを使用し、designation_id と dept_id には 2 つのコンボ ボックスを使用しました。 dept_id と destination_id は tbl_emp の外部キーです。また、コンボ ボックスのプロパティも使用しました。どなたか、エラーの内容と、コンボ ボックスのコードを適切に記述したかどうかを教えてください...

2

SQL インジェクションのアラート - SQL ステートメントを連結しないでください - SQL インジェクションを回避するには、代わりにパラメータ化されたクエリを使用してください - Little Bobby テーブルを確認してください

– marc_s

2020 年 9 月 3 日 16:25

1

@marc_s のコメントを 2 番目に追加しましたが、cmb_desigid.SelectedValue を引用符で囲む必要はありませんか?

– vc 74

2020 年 9 月 3 日 16:32

申し訳ありませんが、何をすればよいのか理解できません

– ksg

2020 年 9 月 3 日 16:33

@vc74 1 つのコンボ ボックスを数値として二重引用符で囲み、もう 1 つのコンボ ボックスを文字列値として一重引用符と二重引用符で囲みました

– ksg

2020 年 9 月 3 日 16:37

2

ユーザー入力に @ があります

– モハメド・エルラシッド

2020 年 9 月 3 日 16:44



------------------------

「パラメータ化されたクエリ」を使用する習慣を身に付ける必要があります。 - これらは、#1 の脆弱性である SQL インジェクションからコードを保護するだけでなく、文字列値への引用符などの追加に関する多くの厄介な問題も解決します。

このコードを試してください:

private void btn_insert_Click(object sender, EventArgs e)
{
    // define the insert query - OleDB uses unnamed, positional parameters 
    string insertQuery = "INSERT INTO tbl_emp (emp_id, emp_name, emp_surname, designation_id, dept_id) " + 
                         "VALUES (?, ?, ?, ?, ?)";
    
    // create command 
    OleDbCommand cmd = new OleDbCommand(insertQuery, con);

    // define parameters - in the proper order! - and set their values
    // The "names" like "@emp_id" that I'm using here are just to make it easier for you to grasp which parameter
    // corresponds to which columns being inserted - you could also name them "p1", "p2" etc. - not very intuitive, though ...
    // Check the *assumptions* I made for the datatypes - not sure if those are
    // really what you have - adapt as needed
    cmd.Parameters.Add("@emp_id", OleDbType.Int).Value = Convert.ToInt32(txt_id.Text);
    
    cmd.Parameters.Add("@emp_name", OleDbType.VarChar, 100).Value = txt_name.Text;
    cmd.Parameters.Add("@emp_surname", OleDbType.VarChar, 100).Value = txt_phone.Text 
    
    cmd.Parameters.Add("@designation_id", OleDbType.Int).Value = cmb_desigid.SelectedValue;
    cmd.Parameters.Add("@dept_id", OleDbType.Int).Value = cmb_deptid.SelectedValue;
    
    // open connection, execute query, close connection
    con.Open();
    cmd.ExecuteNonQuery();
    con.Close();    
    
    MessageBox.Show("Record inserted");
}

一般的な補足として、クエリから返される 1 つの DataTable だけに興味がある場合は、(現在のコードの代わりに) このコードを使用することを強くお勧めします。

private void Form1_Load(object sender, EventArgs e)
{
    con.Open();

    OleDbDataAdapter da = new OleDbDataAdapter("Select * from tbl_designation", con);

    // define and use a "DataTable" - not a "DataSet" (which is overkill for just a single table of data)
    DataTable dt = new DataTable();
    da.Fill(dt);

    cmb_desigid.DataSource = dt;
    cmb_desigid.DisplayMember = "designation_type";
    cmb_desigid.ValueMember = "designation_id";

    con.Close();

2020 年 9 月 3 日 17:15 に回答

マーク_s

マーク_s

740,000

176 個

176 個のゴールドバッジ

1345

銀バッジ 1345 個

銅バッジ 1466 個

銅バッジ 1466 個

1

データ アダプターを使用している場合は、接続を開いたり閉じたりする必要はありません。それ自体でそれを行う方法を知っています

– カイウス・ジャード

2020 年 9 月 5 日 5:47



------------------------

コメントの中で、VS を使用すると、人間が 1 日で行うよりも短時間で、より安全/確実にこれらすべてを実行できると述べました。データベース アクセス コードを書くのは退屈で面倒です。コードを渡す方法は次のとおりです。

フォームやクラスなどを追加するのと同じように、新しいデータセットをプロジェクトに追加します。 dataset1 ではなく、適切な名前にします。 サーバー エクスプローラー ウィンドウを開き、アクセス データベースに接続を追加します。 データベースをデータセットにドラッグします。ポップアップされる長いメッセージ ボックスをよく読んでください。誰もこれを読んでいません、そして彼らはそれを読むべきです。これにより、後でビルドするときに生じる多くの混乱が解決されます。プロセスは、exe が保存されているデータベースを上書きしており、アプリはデータをまったく保存していないようです。 「はい」をクリックします いくつかのテーブルをサーバー エクスプローラーからデータセットにドラッグします。データベーステーブルとテーブルアダプターと同じ列がすべて含まれたデータテーブルの外観ではありません。これはデータベース テーブルではなく、強く型指定されたクライアント側のデータテーブルであり、弱く型指定されたデータセットとデータテーブルを使用して上記のコードで実行していることの改良版です。 tableadapter は、視覚的に接続されているより優れたデータテーブルを操作するように設計された dataadapter の改良版です。 設計されたフォームに切り替える 表示メニュー、その他のウィンドウのサブメニューからデータ ソース ウィンドウを開きます。 ノードの 1 つをデータ ソースからフォーム上にドラッグします。

データ グリッド ビューなど、多くのものが表示されます。ソース、ナビゲーター、データセット、テーブルアダプター、マネージャーを検索します。すべての仕組みを理解するまでは、多くのことを学ぶため、削除しないでください。プログラムを実行します

このアプリは動作し、データをロードし、データを保存します。これまでのところ、コードはまったく記述されていません。 VS がすべてのコードを作成したので、必要に応じて読み取ることができます。コードはディスク上の .Designer.cs ファイルにあります。

アプリを実行し、行を追加し、内容を変更し、[保存] をクリックしてアプリを閉じます。まだアプリを再度実行せず、代わりに bin/debug フォルダーに移動し、そこにあるデータベースをアクセスで開きます。追加/変更したデータを確認する

アクセスを閉じてプロジェクトを再度ビルドし、アクセスで同じ bin/デバッグ データベースを開きます。データが消えているのがわかりますか?ビルド プロセスは、exe が変更したデータベースの上に、プロジェクトから空のデータベースをコピーしました。走った。ビルドするたびに、ここで何が起こっているのかを必ず把握してください。そうしないと、アプリが「保存されない」理由について非常に混乱することになります。 (そうですが、変更はビルド プロセスによって消去されます)

テーブルアダプターについて知っておくべきその他の事項:

複数の選択コマンドを使用できます。データセット デザイナーで右クリックし、別のクエリを追加するだけです。 SELECT * FROM t WHERE id = @id などのパラメーターを使用し、コマンドに FillById などの適切な名前を付けます。 tableadapter はメソッド myTabkeAdapter.FillById(someDatatableHere, 1234) を取得して、行 ID 1234 のデータテーブルを埋めます。 データテーブルを受け取る Update メソッドがあります。これは更新クエリを実行するためだけではありません。 Update は、渡されたデータテーブル全体をスキャンして、挿入する必要がある行を探します。d または削除され、関連する SQL が実行されます。データテーブル行を変更すると、その変更は RowState プロパティによって追跡されます。 rowstate が追加されている場合、行を挿入するためにテーブル アダプターによって挿入が実行されます。行状態が Modified の場合、更新が実行されます。 rowstate が削除されると、削除が実行されます。 Microsoft では、Update を Save などの別の名前で呼ぶべきでした。混乱を招くことが多いためです。

総合生活情報サイト - OKWAVES
総合生活情報サイト - OKWAVES
生活総合情報サイトokwaves(オールアバウト)。その道のプロ(専門家)が、日常生活をより豊かに快適にするノウハウから業界の最新動向、読み物コラムまで、多彩なコンテンツを発信。