[英]How do I delete specific records from a table in visual studio?
我已经多次编写和重写代码,以便在文本框中输入“名称”并单击一个按钮时删除记录,该按钮将删除与输入的名称相关的行。 但是,当我运行程序并单击按钮时,会弹出消息框,指出特定记录已被删除,但是当表显示在数据网格视图中时,记录仍然存在(它们尚未被删除)从表中删除)请检查我的编码并告诉我它有什么问题,我该如何解决? 谢谢:) 另外我不得不说,我只学习了 C# 编程的基本知识。这是我的编码:
private void btnremove_Click(object sender, EventArgs e)
{
con.Open();
DialogResult ans = MessageBox.Show("Are you sure you want to remove the selected records?",
"Confirmation For Membership Cancellation", MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (ans==DialogResult.Yes)
{
string sqldelete = "DELETE FROM membersdetails WHERE Name='" + txtname.Text + "'";
string deletesql = "DELETE FROM currentstatus WHERE Name_='" + txtname.Text + "'";
com = new SqlCommand(sqldelete,con);
com = new SqlCommand(deletesql, con);
SqlDataAdapter sqldataadapter = new SqlDataAdapter(com);
com.ExecuteNonQuery();
MessageBox.Show("Records have been removed- Membership has been cancelled",
"Membership Cancellation", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
con.Close();
com.Dispose();
}
在当前状态下,您的代码存在一些问题:
下面的块,您正在覆盖删除机制的一部分:
com = new SqlCommand(sqldelete,con); com = new SqlCommand(deletesql, con); SqlDataAdapter sqldataadapter = new SqlDataAdapter(com); com.ExecuteNonQuery();
您应该能够将sqldelete
和deletesql
字符串变量合并为 1 个命令,然后可以将其传递给数据库引擎。
从编码的角度看,类应遵守单一职责原则,也就是班担心只做一样东西。 在您当前的代码中,UI 需要考虑保持 UI 更新并保持 DB 更新。 为了解决这个问题,我们通常会创建存储库,其任务是包装数据库操作。 这还允许您测试应用程序的各个层,并在您决定进行任何更改时为您提供更大的灵活性。
照原样,您的代码对 SQL 注入攻击是开放的,请考虑使用准备好的语句来解决这个问题。
除此之外,我看不出您的删除代码有任何本质上的错误。 但是,可能是您的网格没有被刷新(而您认为是)。 检查这一点的最快和最好的方法是使用 SQL Management Studio(或 Azure Data)之类的东西连接到您的数据库并直接查询表。
ExecuteNonQuery()
必须在最后一个新实例之后和之前执行:
com = new SqlCommand(sqldelete,con);
com.ExecuteNonQuery();
com = new SqlCommand(deletesql, con);
com.ExecuteNonQuery();
// Then, you can show the table
string sqlSelect = "SELECT * FROM yourtable WHERE bla bla...";
SqlDataAdapter sqldataadapter = new SqlDataAdapter(sqlSelect, con);
DataTable tbl = new DataTable();
sqldataadapter.Fill(tbl);
yourDataGridView.DataSource = tbl;
试试这个,我希望它可以帮助。
以下是一个示例,可能需要进行一些更改以适应您的代码。 这个想法是使用 BindingSource 设置 DataGridView 数据源,该数据源具有表中的成员详细信息所需的列。 数据操作在一个类中,将前端操作与数据操作分开。 请注意,不需要过大的 SqlDataAdapter。
对于删除操作,最好使用主键,因为它是常量,而名称可能会在某些时候改变。
以下类是读取和删除操作的模型,请确保您了解它不是复制粘贴解决方案,因此在尝试之前花点时间阅读代码。
数据类
using System.Collections.Generic;
using System.Data.SqlClient;
namespace YourNamespace
{
public class MembershipOperations
{
/// <summary>
/// Connection string to your database
/// - change TODO to your environment
/// - Integrated Security (check this too)
/// </summary>
private static readonly string _connectionString =
"Data Source=****TODO****;" +
"Initial Catalog=****TODO****;" +
"Integrated Security=True";
/// <summary>
/// Delete a single member by primary key
/// Recommend adding a try-catch to the open and ExecuteNonQuery lines
/// </summary>
/// <param name="memberIdentifier">Member primary key</param>
/// <returns>
/// Success of the operation
/// </returns>
public static bool RemoveSingleOrder(int memberIdentifier)
{
bool success = false;
string deleteStatement = "DELETE FROM membersdetails WHERE id = @id";
using (var cn = new SqlConnection { ConnectionString = _connectionString })
{
using (var cmd = new SqlCommand { Connection = cn, CommandText = deleteStatement })
{
cmd.Parameters.AddWithValue("id", memberIdentifier);
cn.Open();
success = cmd.ExecuteNonQuery() == 1;
}
}
return success;
}
/// <summary>
/// Provides a list which in the frontend a user can select
/// a member such as a ComboBox or ListBox etc.
///
/// When they select a user you have code to cast the selected item
/// to a MemberDetails instance and pass the primary key to the RemoveSingleOrder
/// method.
///
/// Note in the frontend if there are many members consider providing a incremental
/// search feature to the frontend control displaying member details.
/// </summary>
/// <returns></returns>
public static List<MemberDetails> GetMemberDetails()
{
var memberDetails = new List<MemberDetails>();
/*
* - Create a connection and command object with
* SELECT column names including 'id' primary key
*
* - Use a DataReader to loop through records into
* memberDetails variable
*/
return memberDetails;
}
}
/// <summary>
/// Place in a class file named MemberDetails.cs
/// </summary>
public class MemberDetails
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
// more properties
/// <summary>
/// Optional, can assist with debugging and/or
/// for display purposes
/// </summary>
/// <returns></returns>
public override string ToString() => $"{FirstName} {LastName}";
}
}
使用默认按钮提问的辅助方法是“否”,而不是“是”。
使用 System.Windows.Forms;
namespace YourNamespace
{
public static class Dialogs
{
public static bool Question(string text)
{
return (MessageBox.Show(
text,
Application.ProductName,
MessageBoxButtons.YesNo,
MessageBoxIcon.Question,
MessageBoxDefaultButton.Button2) == DialogResult.Yes);
}
}
}
表格代码
using System;
using System.Windows.Forms;
namespace YourNamespace
{
public partial class Form1 : Form
{
private readonly BindingSource _membersBindingSource = new BindingSource();
public Form1()
{
InitializeComponent();
Shown += Form1_Shown;
}
/// <summary>
/// Setup columns in the IDE for MembersDataGridView that
/// exclude the primary key
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Shown(object sender, EventArgs e)
{
MembersDataGridView.AutoGenerateColumns = false;
_membersBindingSource.DataSource = MembershipOperations.GetMemberDetails();
MembersDataGridView.DataSource = _membersBindingSource;
}
private void RemoveMemberButton_Click(object sender, EventArgs e)
{
if (_membersBindingSource.Current == null) return;
var member = (MemberDetails)_membersBindingSource.Current;
if (!Dialogs.Question($"Remove {member}")) return;
if (!MembershipOperations.RemoveSingleOrder(member.Id))
{
MessageBox.Show($"Failed to remove {member}");
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.