System.ArgumentOutOfRangeException:“索引超出范围。必须为非负数且小于集合的大小。Arg_ParamName_Name”

问题描述 投票:0回答:1

我有这个代码:

using System.Data;
using System.Data.OleDb;


namespace WinFormsApp1
{
    public partial class Form1 : Form
    {
        private int i;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {

            OleDbConnection conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0.;Data Source=C:\\Users\\Админ\\OneDrive\\Рабочий стол\\Lab2bz.mdb");
            OleDbCommand cmd = new OleDbCommand();
            cmd.CommandType = CommandType.Text;

            for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)

                //  cmd.CommandText = "update Tab1 set([Name],[Fname],[Age],[Phone]) where values (?,?,?,?)";
                cmd.Parameters.AddWithValue("@Name", dataGridView1.Rows[i].Cells["Name"].Value.ToString());
            cmd.Parameters.AddWithValue("@Email", dataGridView1.Rows[i].Cells["Email"].Value.ToString());
            cmd.Parameters.AddWithValue("@Date of birth", dataGridView1.Rows[i].Cells["Date of birth"].Value.ToString());
            cmd.Parameters.AddWithValue("@Password", dataGridView1.Rows[i].Cells["Password"].Value.ToString());
            cmd.Parameters.AddWithValue("@Favorite teams", dataGridView1.Rows[i].Cells["Favorite teams"].Value.ToString());
            cmd.Parameters.AddWithValue("@Tickets", dataGridView1.Rows[i].Cells["Tickets"].Value.ToString());
            cmd.Parameters.AddWithValue("@ID", dataGridView1.Rows[i].Cells[0].Value);
            cmd.CommandText = "UPDATE [User] SET Name=@Name, Email=@Email, Date of birth=@Date of birth, Password=@Password, Favorite teams=@Favorite teams, Tickets=@Tickets WHERE ID=@var";

            cmd.Connection = conn;
            conn.Open();
            cmd.ExecuteNonQuery();

            cmd.Parameters.Clear();
            conn.Close();




            System.Windows.Forms.MessageBox.Show("An Item has been successfully added", "Caption", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
            conn.Close();
        }



    }
}

添加

@Email
参数的行会抛出此异常:

System.ArgumentOutOfRangeException:“索引超出范围。必须为非负数且小于集合的大小。Arg_ParamName_Name

循环仅覆盖第一个参数@Name的赋值,后续参数均在循环外。

我该如何解决这个问题?

c# winforms datagridview oledb oledbconnection
1个回答
0
投票

您缺少 for 循环的左/右大括号。因此,只有第一项(对于

Name
)是循环体的一部分,当您到达第二项(
Email
)时,
i
变量已经递增到超过了
Rows
的最后一个索引。收藏。

可以通过添加大括号来解决这个问题,但还有其他改进的空间:

private void button1_Click(object sender, EventArgs e)
{
    // Oof, these column names. No professional names columns like this.
    string SQL = "UPDATE [User] SET Name=@Name, Email=@Email, [Date of birth]=@Date of birth, Password=@Password, [Favorite teams]=@Favorite teams, Tickets=@Tickets WHERE ID=@ID";

    // While I'm here:
    // NEVER NEVER NEVER just store a password like that!
    // This is too important to do wrong even for practice/learning/proof of concept code!

    using var conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0.;Data Source=C:\\Users\\Админ\\OneDrive\\Рабочий стол\\Lab2bz.mdb");
    using var cmd = new OleDbCommand(SQL, conn);

    // set up parameters with specfic types *before* the loop starts
    // Use *exact* types and lengths from the DB here
    cmd.Parameters.Add("@Name", OleDbType.VarWChar, 20);
    cmd.Parameters.Add("@Email", OleDbType.VarWChar, 80);
    cmd.Parameters.Add("@DOB", OleDbtype.Date);
    cmd.Parameters.Add("@Password", OleDbType.Char, 64); // fixed Char, because passwords should be **hashed**, and hashes has fixed sizes
    cmd.Parameters.Add("@FavoriteTeams", OleDbType.VarWChar, 120);
    cmd.Parameters.Add("@Tickets", OleDbType.VarWChar, 80);
    cmd.Parameters.Add("@ID", OleDbType.Integer);

    // open connection ONCE at the beginning
    conn.Open();

    // foreach loop on the rows
    foreach(var Row in dataGridView1.Rows)
    {  // <--- don't forget the braces!

        // now set values for existing parameter objects
        cmd.Parameters[0].Value = row.Cells["Name"].Value;
        cmd.Parameters[1].Value = row.Cells["Email"].Value;
        cmd.Parameters[2].Value = row.Cells["Date of birth"].Value; // ideally, this is an actual Date or DateTime object. If not, considering using Date.Parse() here
        cmd.Parameters[3].Value = HashPassword(row.Cells["Password"].Value); // again: passwords MUST (not optional!) be stored **hashed**!
        cmd.Parameters[4].Value = row.Cells["Favorite teams"].Value;
        cmd.Parameters[5].Value = row.Cells["Tickets"].Value;
        cmd.Parameters[6].Value = row.Cells[0].Value; // ideally an actual integer value. If it's a string, considering using int.Parse() or int.TryParse()

        cmd.ExecuteNonQuery();
        // no need to clear parameters. 
        // We *want* the existing parameter objects to stay valid!
    }

    // No need to close the connection ("using" directive takes care of this for us)
}
© www.soinside.com 2019 - 2024. All rights reserved.