使用 C# 和 SQL 解决 datagridview 中重复条目的最佳方法是啥?
Posted
技术标签:
【中文标题】使用 C# 和 SQL 解决 datagridview 中重复条目的最佳方法是啥?【英文标题】:What is the best way to account for duplicate entries in datagridview with C# and SQL?使用 C# 和 SQL 解决 datagridview 中重复条目的最佳方法是什么? 【发布时间】:2021-05-04 12:46:34 【问题描述】:此 Windows 应用程序在 datagridview 中显示学生信息。双击表格时,会出现另一个表格,用于编辑数据。
当 StudentName 存在重复项时,双击最新条目时,仅显示 StudentName 最早的条目。此外,在编辑特定学生的任何数据时,所有重复的条目也会被编辑!
我正在尝试修改代码,以便它根据 StudentId 而不是 StudentName 加载数据。另一种想法是对代码进行更改,以便用户不能输入重复的条目。
解决这个问题的最佳方法是什么?
ViewStudentForm.cs
private void StudentDataGridView_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
if(StudentDataGridView.Rows.Count > 0)
string studentName = StudentDataGridView.SelectedRows[0].Cells[1].Value.ToString();
StudentForm studentForm = new StudentForm();
studentForm.StudentName = studentName;
studentForm.IsUpdate = true;
studentForm.ShowDialog();
LoadDataIntoDataGridView();
private void LoadDataIntoDataGridView()
using (SqlConnection con = new SqlConnection(AppConnection.GetConnectionString()))
using (SqlCommand cmd = new SqlCommand("usp_Students_LoadDataIntoDataGridView", con))
cmd.CommandType = CommandType.StoredProcedure;
if (con.State != ConnectionState.Open)
con.Open();
DataTable dtStudents = new DataTable();
SqlDataReader sdr = cmd.ExecuteReader();
dtStudents.Load(sdr);
StudentDataGridView.DataSource = dtStudents;
StudentForm.cs
public string StudentName get; set;
public bool IsUpdate get; set;
private void SaveButton_Click(object sender, EventArgs e)
//Do Insert Process
using (SqlConnection con = new SqlConnection(AppConnection.GetConnectionString()))
using (SqlCommand cmd = new SqlCommand("usp_Students_InsertNewStudent", con))
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@StudentName", StudentNameTextBox.Text.Trim());
cmd.Parameters.AddWithValue("@Age", AgeTextBox.Text.Trim());
cmd.Parameters.AddWithValue("@Gender", GenderTextBox.Text.Trim());
cmd.Parameters.AddWithValue("@Description", DescriptionTextBox.Text.Trim());
if (con.State != ConnectionState.Open)
con.Open();
cmd.ExecuteNonQuery();
MessageBox.Show("Student is successfully added in the database.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
ResetFormControl();
usp_Students_InsertNewStudent 的存储过程
ALTER PROCEDURE [dbo].[usp_Students_InsertNewStudent]
(
@StudentName NVARCHAR(200)
,@Age NVARCHAR(50)
,@Gender NVARCHAR(50)
,@Description NVARCHAR(MAX)
,@Image IMAGE
,@CreatedBy NVARCHAR(50)
)
AS
BEGIN
INSERT INTO [dbo].[Students]
([StudentName]
,[Age]
,[Gender]
,[Description]
,[Image]
,[CreatedBy]
,[CreatedDate])
VALUES
(
@StudentName
,@Age
,@Gender
,@Description
,@Image
,@CreatedBy
,GETDATE()
)
END
【问题讨论】:
有很多方法可以解决这个问题。我会在数据库端进行数据验证,因为我认为多个客户端可以同时访问数据库。恕我直言,usp_Students_InsertNewStudent
应该返回插入是否发生。并且模式应该有约束防止你不想进入表的重复项。
没有足够的信息来回答您的问题
首先,我认为您需要对学生姓名列进行唯一约束。这将防止重复。至于如何更改存储过程,这取决于你。数据完整性是第一位的。当您违反上述约束时,您可以简单地捕获 specific 异常并告诉用户这是一个重复的学生姓名。
IMO 试图对 StudentName
施加唯一约束是一个错误的想法。人们有重复的名字,这是事实或生活。您会遇到许多重复的常用名称,例如“John Smith”。似乎双击处理程序应该提取 StudentId
并将其传递给 StudentForm 详细信息。同样,插入存储过程应该捕获scope_identity()
,以便它可以通过output
参数返回新插入记录的StudentId
。
rel - 不要使用addwithvalue。
【参考方案1】:
一些事情:
-
您需要确定现实世界中对您的学生构成独特性的事物。即使是学生姓名、年龄和性别的组合也不会是唯一的。这就是为什么学校会给出一个唯一标识学生的学生 ID。一旦您知道那是什么,就将其添加到您的表中并对其施加唯一约束。
设置后,您需要在前端进行验证,以防止在用户发送重复数据时在数据库中发生错误。这看起来是一个桌面应用程序,前端和后端之间没有层所以应该尽快检查数据库并立即给用户反馈。
如果出于某种原因,您不能执行 #2,那么在您的存储过程中,您可以在插入之前检查是否存在,因为如果您不检查,您的约束将抛出一个错误,如果未处理将使您的应用崩溃。
ALTER PROCEDURE [dbo].[usp_Students_InsertNewStudent]
(
@StudentName NVARCHAR(200)
,@Age NVARCHAR(50)
,@Gender NVARCHAR(50)
,@Description NVARCHAR(MAX)
,@Image IMAGE
,@CreatedBy NVARCHAR(50)
)
AS
BEGIN
if not exists (select 'x' from dbo.Students where uniquekey=@passedinuniquekey)
BEGIN
INSERT INTO [dbo].[Students]
([StudentName]
,[Age]
,[Gender]
,[Description]
,[Image]
,[CreatedBy]
,[CreatedDate])
VALUES
(
@StudentName
,@Age
,@Gender
,@Description
,@Image
,@CreatedBy
,GETDATE()
)
END
END
最后,我会在调用这个存储过程的实际代码中这样做
int rowsAffected = cmd.ExecuteNonQuery();
if (rowsAffected>0)
MessageBox.Show("Student is successfully added in the database.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
ResetFormControl();
else
// Failed message here
【讨论】:
【参考方案2】:我为 ViewStudentForm.cs 中的双击处理程序更改了一些代码
在这种情况下,我认为根据 Id 而不是学生姓名执行加载操作会更好。
private void StudentDataGridView_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
if(StudentDataGridView.Rows.Count > 0)
int StudentId = Convert.ToInt32(StudentDataGridView.SelectedRows[0].Cells[0].Value);
StudentForm studentForm = new StudentForm();
studentForm.StudentId = StudentId;
studentForm.IsUpdate = true;
studentForm.ShowDialog();
LoadDataIntoDataGridView();
【讨论】:
这不是“更好”。 逻辑上正确使用要传递给另一个“进程”以执行某些操作的实体的主(或备用)键值。不要开始做出假设并传递任何东西。您的表单上是否没有某种编辑按钮可以执行完全相同的操作?也许是 rt-click 的弹出菜单?你要把相同的代码放在多个地方吗?以上是关于使用 C# 和 SQL 解决 datagridview 中重复条目的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
winform c# Datagridview 选中行 急!!!
使用 c# 和 oledb 查询更新 Ms-Access 2010 中的列值
使用 C# 和 SQL 解决 datagridview 中重复条目的最佳方法是啥?
如何实现c# winform DataGridView添加一行,添加数据后,保存到数据库?