StuSelect=0 的學生姓名顯示在 ListBox。ListBox 某行:將該生 StuSelect 置 1,下次查詢自動排除。ListBox 綁定顯示文本(StuName)與隱藏值(StuId)SelectedIndexChanged 事件獲取選中行的 StuIdExecuteNonQuery 執行更新btnQuery:查詢按鈕lbStudents:ListBox,屬性 DisplayMember="StuName"、ValueMember="StuId"private void btnQuery_Click(object sender, EventArgs e) {
string connStr = "Server=.;Database=School;Uid=sa;Pwd=123;";
string sql = "SELECT StuId, StuName FROM Students WHERE StuSelect = 0";
using (SqlConnection conn = new SqlConnection(connStr))
using (SqlDataAdapter da = new SqlDataAdapter(sql, conn)) {
DataTable dt = new DataTable();
da.Fill(dt);
lbStudents.DataSource = dt;
lbStudents.DisplayMember = "StuName";
lbStudents.ValueMember = "StuId"; // 關鍵:隱藏綁定主鍵
}
}
private void lbStudents_SelectedIndexChanged(object sender, EventArgs e) {
if (lbStudents.SelectedValue == null) return; // 防止綁定時觸發
int stuId = Convert.ToInt32(lbStudents.SelectedValue);
string connStr = "Server=.;Database=School;Uid=sa;Pwd=123;";
string sql = "UPDATE Students SET StuSelect = 1 WHERE StuId = @id";
using (SqlConnection conn = new SqlConnection(connStr))
using (SqlCommand cmd = new SqlCommand(sql, conn)) {
cmd.Parameters.AddWithValue("@id", stuId); // 參數化防注入
conn.Open();
int rows = cmd.ExecuteNonQuery();
if (rows > 0)
MessageBox.Show($"學生 {lbStudents.Text} 已標記選中");
}
}
| 痛點 | 優化方案 |
|---|---|
| 頻繁開關連接 | 使用連接池(默認開啟),或單例 SqlConnection 配合 using 確保釋放 |
| UI 凍結 | 異步 await cmd.ExecuteNonQueryAsync() + Task.Run 包裹 |
| 並發衝突 | 加樂觀鎖 WHERE StuId=@id AND StuSelect=0,rows==0 提示「已被他人選中」 |
| 硬編碼連接串 | 移至 app.config connectionStrings 節點,ConfigurationManager.ConnectionStrings["SchoolDB"].ConnectionString 讀取 |
ValueMember:SelectedValue 為 DataRowView,需 ((DataRowView)lbStudents.SelectedItem)["StuId"] 取值,易出錯。SelectedIndexChanged 在 DataSource 賦值時也會觸發,務必加 if (lbStudents.SelectedValue == null) return; 守衛。"UPDATE ... WHERE StuId=" + stuId 極度危險,**永遠用參數化**。核心模式:ListBox 綁定 DataTable + ValueMember 綁主鍵 + SelectedIndexChanged 取值 + 參數化 UPDATE。掌握此模式,WinForm 數據交互場景通殺。