有关于此的一些教程,但我假设我必须实现一些错误,因为我从组合教程中遵循的代码不能正常工作。
这些是教程:https://youtu.be/_i4mYXSaD4w,https://youtu.be/_sB0A6FIhUM
我正在尝试创建一个显示一些基本数据的DataGridView,只有4列信息。我希望用户能够添加,更新和删除信息行。我在SQL数据库中手动创建了一行信息,以避免在加载程序时出现“捕获”。
我已经将我的SQL数据库信息的1行加载得很好,但是当我编辑信息并单击我的更新按钮时,它似乎无法在SQL端工作,即使程序端工作。我的意思是,我有一个消息框确认它已被更新,但是当我关闭应用程序并再次运行它时,它会加载旧数据,当我仔细检查数据库时,它还没有更新。如果有人可以帮我调整这个,那么当我向DataGridView添加信息行或编辑行,并让SQL文件实际收到更改/更新时,我会很感激。这是我的代码:
public partial class Form1 : Form
{
SqlConnection con;
SqlDataAdapter sda;
DataTable dt;
SqlCommandBuilder scb;
private int rowIndex = 0;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
con = new SqlConnection(Properties.Settings.Default.SchoolConnectionString);
con.Open();
sda = new SqlDataAdapter("SELECT * FROM School", con);
dt = new DataTable();
sda.Fill(dt);
dataGridView1.DataSource = dt;
}
catch (Exception ex)
{
MessageBox.Show("Error\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void UpButton_Click(object sender, EventArgs e)
{
try
{
scb = new SqlCommandBuilder(sda);
sda.Update(dt);
MessageBox.Show("Information Updated", "Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
//button to refresh the data without need to close the app
private void RefButton_Click(object sender, EventArgs e)
{
try
{
con = new SqlConnection(Properties.Settings.Default.SchoolConnectionString);
con.Open();
sda = new SqlDataAdapter("SELECT * FROM School", con);
dt = new DataTable();
sda.Fill(dt);
dataGridView1.DataSource = dt;
}
catch (Exception ex)
{
MessageBox.Show("Error\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void CloseButton_Click(object sender, EventArgs e)
{
Application.Exit();
}
//BROKEN - supposed to bring up a menu item to delete the row
private void dataGridView1_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
this.dataGridView1.Rows[e.RowIndex].Selected = true;
this.rowIndex = e.RowIndex;
this.dataGridView1.CurrentCell = this.dataGridView1.Rows[e.RowIndex].Cells[1];
this.contextMenuStrip1.Show(this.dataGridView1, e.Location);
contextMenuStrip1.Show(Cursor.Position);
}
}
private void contextMenuStrip1_Click(object sender, CancelEventArgs e)
{
if (!this.dataGridView1.Rows[this.rowIndex].IsNewRow)
{
this.dataGridView1.Rows.RemoveAt(this.rowIndex);
}
}
}
现在,我不确定的是我从其中一个教程改变的一件事是,他们使用的是数据集而不是数据表,但据我所知,除了能够容纳多个表的数据集之外结构,拉动数据或更新数据没有区别。由于我没有大量的数据和不同的表可供使用,我觉得DataTable足以让我使用这个程序。
此外,在我的数据库中,我有一个整数的主键和4列文本。我宁愿避免像行号这样的整数的愚蠢列,只是让我的第一个文本列成为主键,但是当我尝试这样做并更新数据库时,它会抛出错误。如果有办法做到这一点,我会理解如何,或者是否有办法隐藏第一个行号列拉取主键的整数值,并让它自动递增和/或调整此值根据编辑,更改和添加的新行,这将是伟大的。为了清理,如果我添加第2,3和4行,我希望自动生成这些值,并使该列不可见。就目前而言,我必须在那里手动输入整数。
感谢您提供任何帮助和建议。
更新#1:
好的,所以提出一些建议,我尝试使用以下格式的DataSet:
private void Form1_Load(object sender, EventArgs e)
{
try
{
con = new SqlConnection(Properties.Settings.Default.SchoolConnectionString);
con.Open();
sda = new SqlDataAdapter("SELECT * FROM School", con);
ds = new DataSet();
sda.Fill(ds, "e");
dataGridView1.DataSource = ds.Tables["e"];
}
catch (Exception ex)
{
MessageBox.Show("Error\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void UpButton_Click(object sender, EventArgs e)
{
try
{
scb = new SqlCommandBuilder(sda);
sda.Update(ds, "e");
MessageBox.Show("Information Updated", "Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
我尝试使用以下格式提供的第一个答案中给出的格式再次使用DataTable,但有两种方式:1没有SqlCommandBuilder的新实例,还有一个用于: WITH:
private void Form1_Load(object sender, EventArgs e)
{
try
{
con = new SqlConnection(Properties.Settings.Default.SchoolConnectionString);
con.Open();
sda = new SqlDataAdapter("SELECT * FROM School", con);
dt = new DataTable();
sda.Fill(dt);
dataGridView1.DataSource = dt;
}
catch (Exception ex)
{
MessageBox.Show("Error\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void UpButton_Click(object sender, EventArgs e)
{
try
{
scb = new SqlCommandBuilder(sda);
newDT = dt.GetChanges();
if (newDT != null)
{
sda.Update(newDT);
}
MessageBox.Show("Information Updated", "Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
WITHOUT:此版本产生一个错误,指出:“在传递带有修改行的DataRow集合时,Update需要有效的UpdateCommand。”
private void Form1_Load(object sender, EventArgs e)
{
try
{
con = new SqlConnection(Properties.Settings.Default.SchoolConnectionString);
con.Open();
sda = new SqlDataAdapter("SELECT * FROM School", con);
dt = new DataTable();
sda.Fill(dt);
dataGridView1.DataSource = dt;
}
catch (Exception ex)
{
MessageBox.Show("Error\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void UpButton_Click(object sender, EventArgs e)
{
try
{
newDT = dt.GetChanges();
if (newDT != null)
{
sda.Update(newDT);
}
MessageBox.Show("Information Updated", "Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Sooooo,我很难过。除了没有SqlCommandBuilder的那个之外的所有内容都会触发更新的消息框,但它们都没有实际将更改保存到sql数据库。
答案 0 :(得分:0)
在我看来,你永远不会设置SQL更新语句,只能选择语句。
您需要添加以下内容:
sda.UpdateCommand = "UPDATE TABLE SET ..."
或者创建一个新的dataAdapter /命令来处理更新
一旦你有了这个,在sda上调用update应该可行。
修:
如果是我,我会使用SqlCommand作为更新语句。
private void UpButton_Click(object sender, EventArgs e)
{
try
{
using(con = new SqlConnection(Properties.Settings.Default.SchoolConnectionString))
{
con.Open();
string sqlCommand = "Update (Table) set value=@Value where id=@ID";
SqlCommand cmd = new SqlCommand(sqlCommand, con);
cmd.Parameters.AddWithValue("@Value", updatedValue);
cmd.Parameters.AddWithValue("@ID", idOfRowToUpdate);
int rowsAffected = cmd.ExecuteNonQuery();
if(rowsAffected == 1)
{
MessageBox.Show("Information Updated", "Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
con.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
注意事项:
您需要从表中获取要更新的值,并将其替换为UpdatedValue和idOfRowToUpdate。
您需要为表格形成UPDATE命令。
“使用”括号可帮助您正确处理连接对象。
从技术上讲,使用括号con.Close()不是必需的。我这样做是为了以防万一。
修订版#2:
好的,我对SqlDataAdapter以及它在数据表方面的功能做了一些研究,看起来这比我想象的要容易得多。
您应该可以将此新代码放入UpButton_Click方法并使其正常工作:
try
{
DataTable newDT = dt.GetChanges();
if(newDT != null)
{
sda.Update(newDT);
}
MessageBox.Show("Information Updated", "Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
根据This StackOverflow Article,这应该是您进行更新所需的全部内容。
答案 1 :(得分:0)
好吧,多亏了谷歌搜索并通过本网站上的其他问题进行梳理,我发现有人回答了一个类似的问题让我意识到事实上我错过了一些简单的事情。因此,如果有其他人遇到这个问题,我想我会发布可能导致此问题的类似错误。
所以,我没有意识到,Visual Studio正在\ bin \ debug文件夹中创建我的数据库的临时版本。 (如果有办法关闭该功能,我很乐意听到它,因为我觉得这很愚蠢)无论出于何种原因,如果你在Sever Explorer中打开找到.mdf文件,手动添加或删除该数据库中的信息在运行时会反映在程序中,因为它会查找此文件,制作该文件的副本,然后在您运行应用程序进行测试时从那里开始工作。令人失望的事实是(再次,除非我错过了阻止这种情况发生的地方),它不会将您对临时版本所做的这些更改横向复制到您首先创建的主.mdf文件中。
所以,这就是我没有看到任何变化的原因,因为我正在查看主数据库文件,而实际上它并不起作用。一旦我发现如何从Visual Studio中找到临时版本,并且我查询了该文件数据库,我确实看到了这些更改。为清楚起见,我最初尝试过的多个版本实际上都在工作。所以,我在上面尝试的所有解决方案除了我提到它之外由于缺少SqlCommandBuilder调用而产生错误,实际上是更新临时数据库。
作为旁注,来自Visual Studio,C#,SQL新手的观点,我对SQL数据库和DataGridView的广泛教程和信息感到惊讶,这在教程的过程中没有注意到。甚至我观看的Youtube视频也没有明确表明,当他们“证明”更新正在发生时,他们并没有明白他们正在检查临时数据库,而不是主数据库。