指定的 LINQ 表达式包含对与不同上下文关联的查询的引用

Posted

技术标签:

【中文标题】指定的 LINQ 表达式包含对与不同上下文关联的查询的引用【英文标题】:The specified LINQ expression contains references to queries that are associated with different contexts 【发布时间】:2011-07-30 07:07:47 【问题描述】:

我知道在 *** 上有类似的问题 - 我查看了它们并认为我的问题有些相似,但无法通过查看任何其他问题/答案来找到解决方案。 尝试执行以下代码时出现错误:

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

据我所知,我没有使用多个上下文?

【问题讨论】:

【参考方案1】:

我不明白为什么你会在你指出的那一行得到一个异常,但我认为代码有两个缺陷:你在这个方法中实例化了 4 个不同的上下文(虽然我没有看到你混合了那些上下文)并且您不处置任何一个。 (数据库上下文引用一个外部资源(数据库连接),显式地处理它是一个很好的做法。)

尝试重写它,使您只有一个上下文dbContextSaveChanges 只被调用一次,并且这个单个上下文被放置在方法的末尾(通过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 将执行数据库事务也很重要,因此它是一个 All-Or-Nothing 操作。我可以想象这在你的方法中也很重要。例如,您使用Increment the number of occupants in the room.Add the student to a bed. 评论的两个操作,它们不应该同时发生或都不发生以避免数据库中的不一致状态吗?根据您的不同上下文,第一个操作可能成功但第二个操作失败,从而使您的数据在数据库中处于不一致的状态。

【讨论】:

哇!谢谢!这非常有帮助。我认为我对这个主题的理解扩大了 2 倍。我将尝试按照您的建议重写代码,并让您知道它是如何进行的。 :) 需要一点时间来适应这一切,但很快就会开始变得更有意义! :)【参考方案2】:

你不能一通电话得到身份证吗?

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

从外观上看,您正在调用上下文的多个实例。按照其他答案的建议尝试使用块

【讨论】:

以上是关于指定的 LINQ 表达式包含对与不同上下文关联的查询的引用的主要内容,如果未能解决你的问题,请参考以下文章

指定的 LINQ 表达式包含对与不同上下文关联的查询的引用

指定的 LINQ 表达式包含对与不同上下文关联的查询的引用

错误:“指定的 LINQ 表达式包含对与不同上下文关联的查询的引用”[重复]

指定的 LINQ 表达式包含对与 c# 中的不同上下文错误关联的查询的引用

包含对与不同上下文关联的查询的引用的 LINQ 表达式

(Linq/Lambda) 使用 2 个 DBContext 连接 2 个或更多表