Я не понимаю, почему вы можете получить исключение в указанной вами строке, но код, на мой взгляд, имеет два недостатка: вы создаете 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.
, не должны ли они произойти ни с обеими, ни с одной из них, чтобы избежать противоречивого состояния в базе данных?В разных контекстах может случиться так, что первая операция будет успешной, а вторая - неудачной, и ваши данные будут в несогласованном состоянии в БД.