Я видел этот вопрос много раз и на нескольких форумах. Я попробовал, и вот полный ответ для тех, кто на это смотрел.
LinQ не был создан для доступа. Однако многие запросы будут работать с Access, включая процедуру удаления. Так что, по моему мнению, при работе с Access есть только два критических недостатка:
- невозможно сохранить данные.
- не в состоянии перетаскивать объекты в базу данных
Вставить не удастся с ошибкой «отсутствует точка с запятой (;)». Это связано с тем, что процедура сохранения LinQ была сделана для сохранения данных и получения идентификатора первичного ключа записи, сохраненной за один раз. Мы знаем, что вы не можете выполнять несколько операторов SQL в Access, поэтому это является причиной этой ошибки.
Обновление не будет выполнено с ошибкой «запись не найдена». Процедура обновления приведет к поиску обновленной записи и обновлению. Я не могу сказать, почему он не может его найти, когда обычный запрос LinQ для поиска записи работает нормально.
Поскольку использование LinQ дает много преимуществ, я понял, как обойти этот недостаток, и в то же время пользовался другими преимуществами в моем приложении. Вот как (NB: Мои коды находятся на VB.net, но вы можете конвертировать при необходимости):
Создайте класс LinQ to SQL (.dbml) для управления вашим LinQ по базе данных доступа и способ управления процедурой сохранения. Ниже приведены полные процедуры того, что я создал, и теперь я без проблем работаю с LinQ to Access:
Добавьте 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
DetailForm
Код для установки контрольных значений
Private 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
Вам придется добавить объекты данных в базу данных вручную, поскольку вы не можете перетаскивать их при использовании Access. Также обратите внимание, что вам придется правильно настроить все свойства полей в окнах свойств. Некоторые свойства не устанавливаются при добавлении полей.
Код для сохранения
Открытая функция SaveAccountType (Необязательный тип ByVal 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())
Последняя часть кода выше - это то, что возвращает вам идентификатор сохраненной записи. Лично я обычно делаю эту опцию, потому что она мне не нужна в большинстве случаев, поэтому мне не нужно добавлять эти накладные расходы при извлечении данных каждый раз, когда запись сохраняется, я рад просто запись была сохранена.
Это накладные расходы, добавленные в LinQ, что приводит к сбою вставки с 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 для доступа! Удачного кодирования:)