无法访问与 Left Outer Join 连接的模型元素

Can't get access to a model element that is connected with a Left Outer Join

我在这方面经验不足。我认为我已正确设置 LINQ 语句以从多个 table 获取数据,包括我需要 Left Outer Join 的数据。但是我无法获得 HTML.DISPLAYFOR 语句来查看模型中与左外连接连接的任何元素。 (这是 Visual Studio 2017 年内的 VB.net)我浏览了整个网络,甚至浏览了 Whosebug 论坛。我发现的要么是在 C# 中(我正在慢慢学习),要么是语法太旧而无法在我的系统上运行。我在任何地方都找不到任何人试图使用 Displayfor 函数来显示使用左外连接从 SQl 服务器拉出的字段。帮忙?

MemberApointments 模型:

Partial Public Class MemberAppointment
    Public Property AppointmentID As Integer
    Public Property MemberEventID As Integer
    Public Property HospitalID As Integer
    Public Property ActualHospitalID As Nullable(Of Integer)
    Public Overridable Property Hospital As Hospital

医院型号:

Partial Public Class Hospital
    Public Property HospitalID As Integer
    Public Property HospitalShortName As String
    Public Overridable Property MemberAppointments As ICollection(Of MemberAppointment) = New HashSet(Of MemberAppointment)

控制器:

这是原始编码:

Public Function Index(id As Integer?, Optional ByVal page As Integer = 0) As ActionResult
        Dim ptsdAppt As IEnumerable(Of MemberAppointment) _
        = From s In db.MemberAppointments Where s.AppointmentID = id
          Group Join ah In db.Hospitals On s.ActualHospitalID Equals ah.HospitalID Into Group
          From ah In Group.DefaultIfEmpty()
          Select s

根据@Cais Jard 的评论,我尝试了这个:

Dim ptsdAppt = From m In db.Members Where m.MemberID = id
                           Join l In db.EventHistories On l.MemberID Equals m.MemberID
                           Join s In db.MemberAppointments On l.MemberEventID Equals s.MemberEventID
                           Group Join ah In db.Hospitals On s.ActualHospitalID Equals ah.HospitalID Into acthos = Group
                           From ah2 In acthos.DefaultIfEmpty()
                           Select New With {.Members = m,
                               .EventHistories = l,
                               .MemberAppointments = s,
                               .ActualHospital = ah2
                               }
           Return View(ptsdAppt)
        End Function

第三次尝试: 我正在更改其他人的旧代码,看起来像这样。由于 HospitalID 字段上的外键,如果 HospitalShortName 存在,我可以轻松获取它:

Dim ptsdAppt As IEnumerable(Of MemberAppointment) = From s In db.MemberAppointments
     Join l In db.EventHistories On l.MemberEventID Equals s.MemberEventID
     Join m In db.Members On l.MemberID Equals m.MemberID
     Where m.MemberID = id
     Select s

我有 SQL 方面的经验,但没有 LINQ 方面的经验。在 Member Appointment table 中,有 2 个 hospitalID 字段(HospitalID 和 ActualHospitalID),如果它们(独立)存在,我需要与医院 table 中的每个相关联的 ShortName。如果我要使用 SQL,我会这样编码:

Select 
    s.HospitalID,
    h.HospitalShortName,
    s.ActualHospitalID,
    sh.HospitalShortName
From members as m
    join EventHistory As l 
        on l.MemberID = m.MemberID
    join MemberAppointments as s 
        on l.MemberEventID = s.MemberEventID
    left outer join Hospitals As h 
        on s.HospitalID = h.HospitalID 
    left outer join Hospitals As sh 
        on s.ActualHospitalID = sh.HospitalID 
Where m.SSN = '1'

索引视图:

@ModelType IEnumerable(Of PtdrWeb.MemberAppointment)

@For Each item In Model
    Dim currentItem = item
        <div Class="four columns">
@*because there is a foreign key on the MemberAppointment table to the Hospital table using the HospitalID in both tables, this always gives me the right values *@
            @Html.DisplayFor(Function(modelItem) currentItem.HospitalID)
            @Html.DisplayFor(Function(modelItem) currentItem.Hospital.HospitalShortName)
        </div>
        <div Class="four columns">
@*on this one, I need the HospitalShortname where the MemberAppointment table is connect to the Hospital table with the ActualHospitalID=HospitalID, what I'm getting the the HospitalShortName associated with the MemberAppointment.HospitalID field.*@
            @Html.DisplayFor(Function(modelItem) (currentItem.ActualHospitalID))
            @Html.DisplayFor(Function(modelItem) (currentItem.Hospital.HospitalShortName))
        </div>
Next

在过去的一周里,我使用了 select 语句的一百种不同组合...它要么抛出错误(某些内容为空),要么不抛出错误...但在每种情况下,在第二种情况下我都无法获得正确的 HospitalShortName。

要么 LINQ 语句错误,要么我应该使用除 Displayfor 函数之外的其他东西......我不知所措。

我不太明白你为什么要采用这种方法;我想我只是将 ActualHospital 键转到 Hospital table 并让 EF 创建一个 nav 属性 要么是 Hospital 要么 Nothing(FKs 在子端可以为 null)但这就是我认为你正在尝试做:

设置一些示例数据,与您的查询无关

    'some demo fluff
    Dim hs As New List(Of Hospital) From {
        New Hospital With {.HospitalID = 1, .HospitalShortName = "New York"},
        New Hospital With {.HospitalID = 2, .HospitalShortName = "Chicago"}
    }

    Dim mas As New List(Of MemberAppointment) From {
        New MemberAppointment With {.ActualHospitalID = 1, .AppointmentID = 1, .MemberEventID = 1},
        New MemberAppointment With {.ActualHospitalID = 1, .AppointmentID = 1, .MemberEventID = 2},
        New MemberAppointment With {.ActualHospitalID = 1, .AppointmentID = 2},
        New MemberAppointment With {.ActualHospitalID = 2, .AppointmentID = 1},
        New MemberAppointment With {.ActualHospitalID = 3, .AppointmentID = 1},
        New MemberAppointment With {.ActualHospitalID = Nothing, .AppointmentID = 1}
    }

执行加入的查询

    'the nuts and bolts
    Dim ptsdAppt = From ma In mas Where ma.AppointmentID = 1
                   Group Join h In hs On ma.ActualHospitalID Equals h.HospitalID Into g = Group
                   From gg In g.DefaultIfEmpty()
                   Select New With {
                      .MemberAppointment = ma,
                      .ActualHospital = gg
                  }

此输出是一个对象列表,这些对象具有 MemberAppointment 属性 和 ActualHospital 属性,该属性可能是 Hospital 或 Nothing

我建议您不要费心使用 As 来强制查询类型;它们将由编译器推断出来,这使得使用结果变得容易得多

我的天哪。有一个星期我永远不会回来。在我以前的编程经验中,你只改变了编程,你没有改变数据库。 那是数据库管理员的领域。我一直专注于让 Select 语句起作用,我从来没有想过要更改数据库。谢谢@Caius Jard 的提示。

我将 LINQ 改回原来的 select 语句:

    Dim ptsdAppt As IEnumerable(Of MemberAppointment) _
        = From s In db.MemberAppointments
          Join l In db.EventHistories On l.MemberEventID Equals s.MemberEventID
          Join m In db.Members On l.MemberID Equals m.MemberID
          Where m.MemberID = id
          Select s

然后更改会员预约模型,给我另一个与医院的联系 Table:

Public Overridable Property ActualHospital As Hospital

并向 MemberAppointment 添加外键 table:

ALTER TABLE dbo.MemberAppointments
   ADD CONSTRAINT FK_ActualHospital_Hospitals FOREIGN KEY (ActualHospitalID)
      REFERENCES dbo.Hospitals (HospitalID)

然后我更改了 HTML.DISPLAYFOR 语句以使用新连接:

    @Html.DisplayFor(Function(modelItem) (currentItem.ActualHospital.HospitalShortName))

在 VS 2017 中刷新模型图并修复外键以匹配数据库中的实际内容后...DisplayFor 语句突然开始生成我正在寻找的数据。