将数据保存在 datagridview 中,以便在关闭程序后仍然存在

Posted

技术标签:

【中文标题】将数据保存在 datagridview 中,以便在关闭程序后仍然存在【英文标题】:Saving data in datagridview so that it persists after closing program 【发布时间】:2015-04-24 22:19:47 【问题描述】:

我知道这个主题有很多,但我似乎无法获取这些信息并将其自定义到我的代码中。 我在保存数据时遇到问题,因此当我关闭程序并再次打开时数据仍然存在。这是一个简单的程序,其中数据通过文本框输入到数据网格视图中。起初什么都没有发生,但经过数小时的代码工作后,我开始在 dataAdapter.Update(dt) 行上收到此错误消息:

不支持对多个基表进行动态 SQL 生成。

我知道我的代码没有遵循最佳实践规则,但我对编程很陌生,所以玩得开心。在此先感谢您,我真的很感谢您的帮助。

这是我的代码:

Public Class frmGradeBook
    'data grid view for recording students grades
    Dim connStr As String = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
    "Data Source=GRADEBOOK.accdb"
    Dim sqlStr As String = "SELECT firstName,lastName,firstExam,secondExam,finalExam " & _
                    "FROM Students INNER JOIN Grades ON Students.studentID = Grades.studentID "
    Dim dataAdapter As New OleDb.OleDbDataAdapter(sqlStr, connStr)
    Dim dt As New DataTable()

    'secondary data grid view for displaying students grade
    Dim connStr1 As String = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
    "Data Source=GRADEBOOK.accdb"
    Dim sqlStr1 As String = "SELECT firstName, lastName, finalExam FROM Students INNER JOIN Grades ON Students.studentID = Grades.studentID "
    Dim dataAdapter1 As New OleDb.OleDbDataAdapter(sqlStr1, connStr1)
    Dim dt1 As New DataTable()

Private Sub frmGradeBook_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    dataAdapter.Fill(dt)
    dgvRecordGrades.DataSource = dt

    dataAdapter1.Fill(dt1)
    dgvDisplayGrades.DataSource = dt1

    dgvDisplayGrades.Visible = False
    lstGrade.Visible = False

End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles btnRecord.Click

    dgvDisplayGrades.Visible = False
    dgvRecordGrades.Visible = True
    lstGrade.Visible = False

    'validates the data
    Dim studentID As String = txtID.Text.ToUpper
    Dim row As Integer
    Dim dataGridRow As DataGridViewRow = dgvRecordGrades.Rows(1)

        If IsNumeric(txtFirstExam.Text) And IsNumeric(txtSecExam.Text) And IsNumeric(txtFinalExam.Text) Then
            If (txtFirstExam.Text).ToString().IndexOf(".") = -1 Then
                Dim firstExam As Double = CDbl(txtFirstExam.Text)
                Dim secondExam As Double = CDbl(txtSecExam.Text)
                Dim finalExam As Double = CDbl(txtFinalExam.Text)

                If firstExam <= 100 And secondExam <= 100 And finalExam <= 100 Then
                    If firstExam >= 0 And secondExam >= 0 And finalExam >= 0 Then

                        If studentID = "AJ-123456" Then
                            row = 0
                        ElseIf studentID = "FA-192837" Then
                            row = 1
                        ElseIf studentID = "GG-567876" Then
                            row = 2
                        ElseIf studentID = "GJ-987654" Then
                            row = 3
                        ElseIf studentID = "LS-222333" Then
                            row = 4
                        Else
                            MessageBox.Show("The student ID provided is not valid. Please try again.")
                        End If

                    'records the grades
                        dgvRecordGrades.Item(2, row).Value = firstExam
                        dgvRecordGrades.Item(3, row).Value = secondExam
                        dgvRecordGrades.Item(4, row).Value = finalExam

                    Else
                        MessageBox.Show("Invalid input. Please try again")
                    End If
                Else
                    MessageBox.Show("Invalid input. Please try again")
                End If
            Else
                MessageBox.Show("Please enter whole numbers. Try again.")
            End If

        Else
            MessageBox.Show("Invalid input. Please try again")
        End If


End Sub

Private Sub Button1_Click_2(sender As Object, e As EventArgs) Handles btnPostable.Click
    dgvRecordGrades.Visible = False
    dgvDisplayGrades.Visible = False
    lstGrade.Visible = True

    lstGrade.Items.Clear()

    If Not IsDBNull((dgvDisplayGrades.Item(2, 0).Value)) Then
        lstGrade.Items.Add("3456    " & LetterGrade(CDbl(dgvDisplayGrades.Item(2, 0).Value)))
    Else
        lstGrade.Items.Add("3456    NO GRADE AVAILABLE")
    End If

    If Not IsDBNull((dgvDisplayGrades.Item(2, 1).Value)) Then
        lstGrade.Items.Add("2837    " & LetterGrade(CDbl(dgvDisplayGrades.Item(2, 1).Value)))
    Else
        lstGrade.Items.Add("2837    NO GRADE AVAILABLE")
    End If

    If Not IsDBNull((dgvDisplayGrades.Item(2, 2).Value)) Then
        lstGrade.Items.Add("7876    " & LetterGrade(CDbl(dgvDisplayGrades.Item(2, 2).Value)))
    Else
        lstGrade.Items.Add("7876    NO GRADE AVAILABLE")
    End If

    If Not IsDBNull((dgvDisplayGrades.Item(2, 3).Value)) Then
        lstGrade.Items.Add("7654    " & LetterGrade(CDbl(dgvDisplayGrades.Item(2, 3).Value)))
    Else
        lstGrade.Items.Add("7654    NO GRADE AVAILABLE")
    End If

    If Not IsDBNull((dgvDisplayGrades.Item(2, 4).Value)) Then
        lstGrade.Items.Add("2333    " & LetterGrade(CDbl(dgvDisplayGrades.Item(2, 4).Value)))
    Else
        lstGrade.Items.Add("2333    NO GRADE AVAILABLE")
    End If
End Sub

Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles btnDisplay.Click
    dgvDisplayGrades.Visible = True
    dgvRecordGrades.Visible = False
    lstGrade.Visible = False

    For col As Integer = 2 To 2
        For row As Integer = 0 To 4
            If Not IsDBNull(dgvRecordGrades.Item(col, row).Value) Then
                Dim firstExam As Double = CDbl(dgvRecordGrades.Item(2, row).Value)
                Dim secExam As Double = CDbl(dgvRecordGrades.Item(3, row).Value)
                Dim finalExam As Double = CDbl(dgvRecordGrades.Item(4, row).Value)
                dgvDisplayGrades.Item(2, row).Value = SemAvg(firstExam, secExam, finalExam)
            Else
            End If
        Next
    Next

End Sub


Function SemAvg(firstMid As Double, secondMid As Double, final As Double) As Double
    Dim semAverage As Double
    semAverage = (firstMid + secondMid + (2 * final)) / 4
    Math.Round(semAverage)
    Return semAverage
End Function


Function LetterGrade(semAvg As Double) As String
    Select Case semAvg
        Case Is >= 90
            Return "A"
        Case Is >= 80
            Return "B"
        Case Is >= 70
            Return "C"
        Case Is >= 60
            Return "D"
        Case Else
            Return "F"
    End Select
End Function



Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
    Dim changes As Integer
    Dim commandBuilder As New  _
                            OleDb.OleDbCommandBuilder(dataAdapter)
    changes = dataAdapter.Update(dt)
    If changes > 0 Then
        MessageBox.Show(changes & " changed rows.")
    Else
        MessageBox.Show("No changes made.")
    End If

End Sub


Private Sub frmGradeBook_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
    dataAdapter.Dispose()
    dataAdapter1.Dispose()

End Sub
End Class

【问题讨论】:

【参考方案1】:

我认为以下是问题所在。

您正在填充来自 dataAdapter 的 datatable dt,其中包含以下内容

commandText=

"SELECT firstName,lastName,firstExam,secondExam,finalExam " & _
            "FROM Students INNER JOIN Grades ON Students.studentID = Grades.studentID "

正在从两个表中检索数据。

要从 dataAdapter 获取 自动 更新命令,您必须从 只有一个 具有 主键的表中检索数据。

您不能从多个表中检索以使用 dataAdapter.UpdateCommand 属性。

希望这会有所帮助。

【讨论】:

以上是关于将数据保存在 datagridview 中,以便在关闭程序后仍然存在的主要内容,如果未能解决你的问题,请参考以下文章

怎么将datagridview中修改后的数据通过按钮点击直接保存到数据库啊?

急!在datagridview中修改或增加数据,单击按钮能将写入的数据保存到数据库里?求C#源代码,谢谢交个朋友

将datagridview数据保存到xml

将数据从 datagridview 保存到 XML 并加载

如何实现c# winform DataGridView添加一行,添加数据后,保存到数据库?

c# winform DataGridView添加一行,添加数据后,保存到数据库