Указанное выражение LINQ содержит ссылки на запросы, связанные с разными контекстами.

Я знаю, что в stackoverflow есть похожие вопросы, и я просмотрел их и думаю, что моя проблема несколько похожа, но не смог найти решение, просмотрев любой из этих других вопросов/ответов. Я получаю сообщение об ошибке при попытке выполнить следующий код:

Private Sub btnReserve_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnReserve.Click
    ' Check that the room is still available.
    Dim dbCheckOccupants As New pbu_housingEntities
    Dim hall As String = CStr(Session("hall"))
    Dim room As String = CStr(Session("room"))
    Dim checkOccupants = From p In dbCheckOccupants.Rooms _
                         Let building_id = p.Building1.id _
                         Where p.building_name = hall _
                         Where p.room1 = room _
                         Select p.current_occupancy, p.max_occupancy, p.id, building_id
    If checkOccupants.First.current_occupancy >= checkOccupants.First.max_occupancy Then
        ' If it isn't available, let student know.
        lblResult.Text = "Sorry, this room is now fully occupied. Please choose another room."
    Else
        ' If it is available, add the student to the room.
        Dim AddOccupant As New pbu_housingEntities
        Dim Occupant As New Resident
        Dim gender As String = CStr(Session("gender"))
        Dim person_name As String = CStr(Session("person_name"))
        Dim class_level As String = CStr(Session("class_level"))
        Dim semester As String = CStr(Session("term"))
        Dim people_code_id As String = CStr(Session("people_code_id"))
        Dim first_name As String = CStr(Session("first_name"))
        Dim last_name As String = CStr(Session("last_name"))
        Dim building_id As String = checkOccupants.First.building_id
        Dim room_id As String = checkOccupants.First.id
        Occupant.building = building_id
        Occupant.room = room_id
        Occupant.gender = gender
        Occupant.person_name = person_name
        Occupant.class_level = class_level
        Occupant.semester = semester
        Occupant.people_code_id = people_code_id
        Occupant.create_date = Date.Now
        Occupant.first_name = first_name
        Occupant.last_name = last_name
        AddOccupant.Residents.AddObject(Occupant)
        AddOccupant.SaveChanges()
        ' Increment the number of occupants in the room.
        Dim UpdateRoomOccupancy As New pbu_housingEntities
        Dim UpdateOccupancy = (From p In UpdateRoomOccupancy.Rooms _
                               Where p.building_name = hall _
                               Where p.room1 = room _
                               Select p).First
        UpdateOccupancy.current_occupancy = UpdateOccupancy.current_occupancy + 1
        UpdateRoomOccupancy.SaveChanges()
        ' Add the student to a bed.
        Dim AddBed As New pbu_housingEntities
        Dim UpdateBed = From p In AddBed.Beds _
                        Where p.building = building_id _
                        Where p.room = room_id _
                        Where p.occupant = "" _
                        Select p

        ' Get the student's ID from the residency table.
        Dim GetID = From p In AddBed.Residents _
                    Where p.people_code_id = people_code_id _
                    Order By p.id Descending _
                    Select p

        Dim myID As String = GetID.First.id.ToString

        UpdateBed.First.occupant = myID
        AddBed.SaveChanges()
        lblResult.Text = "Success! You have successfully requested residency in this room!"
    End If
End Sub

Он ловит ошибку в этой строке:

Dim myID As String = GetID.First.id.ToString

Насколько я могу судить, я не использую несколько контекстов?


person Dave Mackey    schedule 05.04.2011    source источник


Ответы (2)


Я не совсем понимаю, почему вы можете получить исключение в указанной вами строке, но, на мой взгляд, в коде есть два недостатка: вы создаете экземпляры 4 разных контекстов в этом методе (хотя я не вижу, чтобы вы смешивали объекты из этих контекстов) и вы не распоряжаетесь ни одним из них. (Контекст базы данных ссылается на внешний ресурс (соединение с базой данных), явное удаление которого является хорошей практикой.)

Попробуйте переписать его так, чтобы у вас был только один контекст dbContext, SaveChanges вызывался только один раз, и этот единственный контекст располагался в конце метода (через блок Using):

Private Sub btnReserve_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnReserve.Click
    ' Check that the room is still available.
    Using (dbContext As pbu_housingEntities = New pbu_housingEntities)
        ' Check that the room is still available.
        Dim hall As String = CStr(Session("hall"))
        Dim room As String = CStr(Session("room"))
        Dim checkOccupants = From p In dbContext.Rooms _
                             Let building_id = p.Building1.id _
                             Where p.building_name = hall _
                             Where p.room1 = room _
                             Select p.current_occupancy, p.max_occupancy, p.id, building_id
        If checkOccupants.First.current_occupancy >= checkOccupants.First.max_occupancy Then
            ' If it isn't available, let student know.
            lblResult.Text = "Sorry, this room is now fully occupied. Please choose another room."
        Else
            ' If it is available, add the student to the room.
            Dim Occupant As New Resident
            Dim gender As String = CStr(Session("gender"))
            Dim person_name As String = CStr(Session("person_name"))
            Dim class_level As String = CStr(Session("class_level"))
            Dim semester As String = CStr(Session("term"))
            Dim people_code_id As String = CStr(Session("people_code_id"))
            Dim first_name As String = CStr(Session("first_name"))
            Dim last_name As String = CStr(Session("last_name"))
            Dim building_id As String = checkOccupants.First.building_id
            Dim room_id As String = checkOccupants.First.id
            Occupant.building = building_id
            Occupant.room = room_id
            Occupant.gender = gender
            Occupant.person_name = person_name
            Occupant.class_level = class_level
            Occupant.semester = semester
            Occupant.people_code_id = people_code_id
            Occupant.create_date = Date.Now
            Occupant.first_name = first_name
            Occupant.last_name = last_name
            dbContext.Residents.AddObject(Occupant)

            ' Increment the number of occupants in the room.
            Dim UpdateOccupancy = (From p In dbContext.Rooms _
                                   Where p.building_name = hall _
                                   Where p.room1 = room _
                                   Select p).First
            UpdateOccupancy.current_occupancy = UpdateOccupancy.current_occupancy + 1

            ' Add the student to a bed.
            Dim UpdateBed = From p In dbContext.Beds _
                            Where p.building = building_id _
                            Where p.room = room_id _
                            Where p.occupant = "" _
                            Select p

            ' Get the student's ID from the residency table.
            Dim GetID = From p In dbContext.Residents _
                        Where p.people_code_id = people_code_id _
                        Order By p.id Descending _
                        Select p

            Dim myID As String = GetID.First.id.ToString

            UpdateBed.First.occupant = myID

            dbContext.SaveChanges()

            lblResult.Text = "Success! You have successfully requested residency in this room!"
        End If
    End Using
End Sub

Если повезет, ошибка исчезнет, ​​и код по-прежнему будет работать так же, как и раньше.

Изменить

Я просто быстро добавляю общее примечание: возможно, у вас есть (неверная) идея, что вам нужен новый контекст для каждого запроса, операции вставки или удаления. Это не так, и на самом деле это плохая практика с высоким риском смешивания объектов в разных контекстах. В большинстве ситуаций вы можете следовать стандартному шаблону в своих методах, например:

' Create one single context
Using (dbContext As pbu_housingEntities = New pbu_housingEntities)

    ' Use here this dbContext for as many queries, Adds, Deletes and Changes
    ' as you need and like

    ' Save ALL Adds, Deletes and Changes you have done in this block
    dbContext.SaveChanges()

End Using

Также важно знать, что SaveChanges будет выполнять транзакцию базы данных, поэтому это операция «все или ничего». Я мог предположить, что это также важно в вашем методе. Например, две операции, которые вы прокомментировали с помощью Increment the number of occupants in the room. и Add the student to a bed., не должны ли они выполняться либо обе, либо ни одна из них, чтобы избежать несогласованного состояния в базе данных? С вашими разными контекстами может быть возможно, что первая операция завершится успешно, а вторая завершится неудачно, оставив ваши данные в несогласованном состоянии в БД.

person Slauma    schedule 05.04.2011
comment
ВАУ! Спасибо! Это очень полезно. Я думаю, что мое понимание этой темы только что расширилось в 2 раза. Я собираюсь попробовать переписать код, как вы предложили, и дам вам знать, как это происходит. :) - person Dave Mackey; 06.04.2011
comment
Требуется некоторое время, чтобы привыкнуть ко всему этому, но вскоре начнет иметь больше смысла!! :) - person Andrew; 06.04.2011

Вы не можете получить идентификатор за один звонок?

Dim MyID = (From p In AddBed.Residents _
                    Where p.people_code_id = people_code_id _
                    Order By p.id Descending _
                    Select p.id).SingleOrDefault()

Вы вызываете несколько экземпляров контекста по внешнему виду. Попробуйте использовать блок, как рекомендует другой ответ

person Andrew    schedule 05.04.2011