You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# Tuple技术问题:如何根据文本框输入动态加载对应测试题目

Fixing the Dynamic Test Loading Exception & Optimizing Your Code

Hey Nils, let's break down why you're hitting that exception when switching from a hardcoded test name to using textBox1 input, and fix up the code to make it more robust.

The Root Cause of Your Exception

That error when setting radioButton1.Text = list[0].Item1 is almost certainly an IndexOutOfRangeException—meaning your list is empty when you try to access the first element. This happens because either:

  • The SQL query didn't return any rows (maybe the test name entered doesn't exist in the database, or there's a typo)
  • There was an issue executing the query (like a database connection problem, or invalid SQL syntax from improper string concatenation)

Step-by-Step Fixes & Improvements

1. Use Parameterized SQL to Avoid Errors & SQL Injection

Never directly concatenate user input into SQL queries—it's a huge security risk (SQL injection) and can break your query if the input has spaces, apostrophes, or special characters. Instead, use a parameterized command:

// Replace your hardcoded SQL with this parameterized version
string query = @"SELECT item_name 
                 FROM TEST_ITEMS I 
                 JOIN TESTS T ON I.test_id = T.test_id 
                 WHERE test_name = @TestName";

SqlCommand cmd = new SqlCommand(query, con);
// Add the parameter from textBox1.Text
cmd.Parameters.AddWithValue("@TestName", textBox1.Text.Trim()); // Trim to avoid accidental whitespace

2. Add Error Handling & Check for Empty Results

Before trying to access list[0], make sure the query returned data and your list isn't empty. Wrap the database logic in a try-catch block to catch any connection/query errors:

private void TestF_Load(object sender, EventArgs e)
{
    list = new List<Tuple<string, string>>();
    tempTable = new DataTable();
    tempTable.Columns.Add("Item1");
    tempTable.Columns.Add("Item2");
    tempTable.Columns.Add("Value");
    var tkey = new DataColumn[] { tempTable.Columns[0], tempTable.Columns[1] };
    tempTable.PrimaryKey = tkey;

    try
    {
        // Ensure the connection is open (or use using statements for better resource management)
        if (con.State != ConnectionState.Open)
            con.Open();

        string query = @"SELECT item_name 
                         FROM TEST_ITEMS I 
                         JOIN TESTS T ON I.test_id = T.test_id 
                         WHERE test_name = @TestName";

        SqlCommand cmd = new SqlCommand(query, con);
        cmd.Parameters.AddWithValue("@TestName", textBox1.Text.Trim());

        SqlDataAdapter da = new SqlDataAdapter(cmd);
        DataTable dt = new DataTable();
        da.Fill(dt);

        // Check if we have any test items
        if (dt.Rows.Count == 0)
        {
            MessageBox.Show($"No test items found for '{textBox1.Text.Trim()}'. Please check the test name.");
            // Disable radio buttons or handle empty state
            radioButton1.Enabled = false;
            radioButton2.Enabled = false;
            return;
        }

        // Generate the binary pairs (optimized loop logic)
        total = dt.Rows.Count;
        for (int i = 0; i < total; i++)
        {
            for (int j = i + 1; j < total; j++)
            {
                list.Add(Tuple.Create(
                    dt.Rows[i]["item_name"].ToString(),
                    dt.Rows[j]["item_name"].ToString()
                ));
            }
        }

        // Randomize the pairings (you mentioned this in comments—let's implement it!)
        Random rng = new Random();
        list = list.OrderBy(x => rng.Next()).ToList();

        // Now safely set the radio button text only if list isn't empty
        if (list.Count > 0)
        {
            radioButton1.Text = list[0].Item1;
            radioButton2.Text = list[0].Item2;
            radioButton3.Text = "Undecided";
            location++;
            total = list.Count;
        }
        else
        {
            MessageBox.Show("No valid item pairs could be generated.");
            radioButton1.Enabled = false;
            radioButton2.Enabled = false;
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show($"Error loading test data: {ex.Message}");
        // Log the exception details for debugging if needed
    }
    finally
    {
        // Always close the connection when done
        if (con.State == ConnectionState.Open)
            con.Close();
    }
}

3. Additional Improvements

  • Using Statements: For better resource management, wrap SqlCommand, SqlDataAdapter, and even the connection in using blocks to ensure they're disposed properly (prevents connection leaks). Example:
    using (SqlConnection con = new SqlConnection("your_connection_string"))
    using (SqlCommand cmd = new SqlCommand(query, con))
    {
        // Your query logic here
    }
    
  • Strongly Typed Access: Instead of dt.Rows[i].ItemArray[0].ToString(), use dt.Rows[i]["item_name"].ToString()—it's more readable and less error-prone if the query column order changes.
  • Randomization: I added the random pairing logic you mentioned in your comments using LINQ's OrderBy with a random number generator.
  • Empty State Handling: The code now shows user-friendly messages and disables radio buttons when no data is found, preventing the original exception.

Why This Works

  • Parameterized queries eliminate SQL injection risks and ensure the test name is passed correctly to the database, even if it has special characters.
  • We explicitly check if the query returned rows and if the list has items before accessing list[0], which stops the IndexOutOfRangeException.
  • Error handling catches any unexpected issues (like connection problems) and tells you exactly what went wrong.

内容的提问来源于stack exchange,提问作者Nils Erickson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:34:37