我在多个论坛上看到过很多次这个问题。我试了一下,对于那些一直在看它的人来说,这是一个完整的答案。
LinQ 不适用于 Access。但是,许多查询都可以使用 Access,包括删除过程。因此,在我看来,使用 Access 时只有两个关键缺陷,它们是:
- 无法保存数据。
- 无法将对象拖放到 dbml 上
插入将失败,并出现错误“缺少分号 (;)”。这是因为 LinQ 保存过程是为了保存数据并一次性检索保存的记录的主键 ID。我们知道您不能在 Access 中执行多个 SQL 语句,所以这就是失败的原因。
更新将失败,并出现错误“找不到记录”。更新过程将寻找要更新的记录然后更新它。当正常的 LinQ 查询查找记录工作正常时,我不知道为什么它找不到它。
因为使用 LinQ 有很多好处,我想出了如何解决这个缺陷,同时在整个应用程序中享受其他好处。就是这样(注意:我的代码在 VB.net 中,但您可以根据需要进行转换):
创建 LinQ to SQL (.dbml) 类来根据访问数据库管理 LinQ,以及管理保存过程的方法。以下是我创建的完整过程,我现在使用 LinQ 访问没有任何问题:
在表单上添加DataGridView。添加用于添加、编辑和删除的按钮
填充网格的代码:
Private Sub ResetForm()
Try
Using db As New AccessDataClassesDataContext(ACCCon)
Dim rows = (From row In db.AccountTypes
Where row.AccountTypeID > 1
Order By row.AccountTypeID Ascending
Select row).ToList()
Me.DataGridView1.DataSource = rows
End Using
Catch ex As Exception
MessageBox.Show("Error: " & vbCr & ex.ToString, "Data Error", MessageBoxButtons.OK)
End Try
End Sub
详细表格
设置控制值的代码
私有子 ResetForm()
Try
If _accountTypeID = 0 Then
Exit Sub
End If
Using db As New AccessDataClassesDataContext(ACCCon)
'Dim rows = (From row In db.AccountTypes
' Where row.AccountTypeID = _accountTypeID
' Order By row.AccountTypeID Ascending
' Select row.AccountTypeID, row.AccountType, row.LastUpdated).ToList()
Dim rows = (From row In db.AccountTypes
Where row.AccountTypeID = _accountTypeID
Select row).ToList()
For Each s In rows
Me.AccountTypeIDTextBox.Text = s.AccountTypeID
Me.myGuidTextBox.Text = s.myGuid
Me.AccountTypeTextBox.Text = s.AccountType
Me.AcHeadIDTextBox.Text = s.AcHeadID
Me.DescriptionTextBox.Text = s.Description
Me.LastUpdatedDateTimePicker.Value = s.LastUpdated
Next
End Using
Catch ex As Exception
End Try
End Sub
LinQToSQLClass
您必须手动将数据对象添加到 dbml,因为在使用 Access 时无法拖放。另请注意,您必须在属性窗口中正确设置字段的所有属性。添加字段时没有设置几个属性。
要保存的代码
Public Function SaveAccountType(Optional ByVal type As String =
"关闭") 作为布尔值
Dim success As Boolean = False
Dim row As New AccountType
Using db As New AccessDataClassesDataContext(ACCCon)
If _accountTypeID > 0 Then
row = (From r In db.AccountTypes
Where r.AccountTypeID = _accountTypeID).ToList()(0)
If String.IsNullOrEmpty(row.AccountTypeID) Then
MessageBox.Show("Requested record not found", "Update Customer Error")
Return success
End If
End If
Try
With row
.myGuid = Me.myGuidTextBox.Text
.AccountType = Me.AccountTypeTextBox.Text
.Description = Me.DescriptionTextBox.Text
.AcHeadID = Me.AcHeadIDTextBox.Text
.LastUpdated = Date.Parse(Date.Now())
End With
If _accountTypeID = 0 Then db.AccountTypes.InsertOnSubmit(row)
db.SubmitChanges()
success = True
Catch ex As Exception
MessageBox.Show("Error saving to Customer: " & vbCr & ex.ToString, "Save Data Error")
End Try
End Using
Return success
End Function
现在替换这两行:
If _accountTypeID = 0 Then db.AccountTypes.InsertOnSubmit(row)
db.SubmitChanges()
类似这样的:
Dim cmd As IDbCommand
cmd = Me.Connection.CreateCommand()
cmd.Transaction = Me.Transaction
cmd.CommandText = query
If myGuid.Trim.Length < 36 Then myGuid = UCase(System.Guid.NewGuid.ToString())
cmd.Parameters.Add(New OleDbParameter("myGuid", row.myGuid))
cmd.Parameters.Add(New OleDbParameter("AccountType", row.AccountType))
cmd.Parameters.Add(New OleDbParameter("Description", row.Description))
cmd.Parameters.Add(New OleDbParameter("AcHeadID", row.AcHeadID))
cmd.Parameters.Add(New OleDbParameter("LastUpdated", Date.Now))
If AccountTypeID > 0 Then cmd.Parameters.Add(New OleDbParameter("AccountTypeID", row.AccountTypeID))
If Connection.State = ConnectionState.Closed Then Connection.Open()
result = cmd.ExecuteNonQuery()
cmd = Me.Connection.CreateCommand()
cmd.Transaction = Me.Transaction
cmd.CommandText = "SELECT @@IDENTITY"
result = Convert.ToInt32(cmd.ExecuteScalar())
上面代码的最后一部分是获取保存记录的 ID。就个人而言,我通常会选择这个选项,因为在大多数情况下我不需要它,所以我不需要在每次保存记录时添加取回数据的开销,我很高兴知道一个记录已保存。
这是添加到 LinQ 的开销,这会导致 Insert 使用 Access 失败。真的有必要拥有吗?我不这么认为。
您可能已经注意到我通常将我的更新和插入过程放在一起,这样可以节省我的时间,并且可以一次性解决插入和更新过程。
删除代码:
Private Sub DelButton_Click(sender As Object, e As EventArgs) Handles DelButton.Click
Using db As New AccessDataClassesDataContext(ACCCon)
Dim AccountTypeID As Integer = Me.DataGridView1.CurrentRow.Cells(0).Value
Dim row = From r In db.AccountTypes Where r.AccountTypeID = AccountTypeID
For Each detail In row
db.AccountTypes.DeleteOnSubmit(detail)
Next
Try
db.SubmitChanges()
Catch ex As Exception
' Provide for exceptions.
MsgBox(ex)
End Try
End Using
End Sub
现在您可以享受 LinQ 访问了!快乐编码:)