Select 可选导航 属性 进入新对象

Select optional navigation property into new object

我有一组业务对象,我正在尝试使用 Entity Framework 查询填充这些对象。 MS-SQL 数据库和 EF 模型都反映了下面的 类。

请注意 ParentTypeChildType 的“0..1 to Many”有关。

问题是我想加载一个 ParentType 对象作为 ChildType 对象的 属性,但是正如所写的那样,如果 ParentType 是 Null,我得到 InvalidOperationException 因为 ParentType 中的物化值是 Null。

另请注意,我不想将 ParentType 数据展平为 ChildType 中的可为空字段,因为稍后我想按整个 ParentType 对象对结果列表进行分组。

Public Class ParentType
    Public Property ParentTypeID as Integer
    Public Property Description as String
End Class

Public Class ChildType
    Public Property ChildTypeID As Integer
    Public Property ParentTypeID As Integer?
    Public Property Description As String

    Public Property ParentType As ParentType

    Public Shared Function GetChildTypes() As IQueryable(Of ChildType)
        Dim db As New DataAccess.MyModelEntities()

        Return (
            From c In db.ChildTypes
            Select New ChildType With {
                .ChildTypeID = c.ChildTypeTypeID,
                .ParentTypeID = c.ParentTypeID,
                .Description = c.Description,
                .ParentType = New ParentType With {
                    .ParentTypeID = c.ParentType.ParentTypeID,
                    .Description = c.ParentType.Description
                }
            }
        )
    End Function
End Class

编辑:试图澄清,我正在寻找的是一种我可以按照所写的方式New ParentType,但只有当c.ParentType不为空时。

哦,伙计 - 我自己过去也曾为此苦苦挣扎过。

在entity framework中,基本上是将导航属性保存为外键。这意味着当您加载具有导航 属性 的实体时,它不会同时加载 属性 类型的实体的属性,因为它只有外键。

如果您想加载相关实体的属性,您必须使用 Eager Loading(Gert Arnold 使用的示例)将其包含在查询中,或者在过程。

在你的特定情况下,我猜你会使用这样的东西:

From c In db.ChildTypes
            Select New ChildType With {
                .ChildTypeID = c.ChildTypeTypeID,
                .ParentTypeID = c.ParentTypeID,
                .Description = c.Description,
                .ParentType = New ParentType With {
                    .ParentTypeID = c.ParentTypeID,
                    .Description = (From parent In db.ParentTypes Select parent.Description Where parent.ParentTypeID = c.ParentTypeID).FirstOrDefault()
                }

或者 Gert 推荐的预加载方式:

Dim childTypesList = db.ChildTypes.Include("ParentTypes").ToListAsync()

最后,我想我将不得不允许创建 ParentType 对象并允许其所有成员都可以为空。对我来说,这不是理想的解决方案,但它使查询按书面方式工作。

Public Class ParentType
    Public Property ParentTypeID as Integer?
    Public Property Description as String
End Class

我可以检查 ParentType.ParentTypeID.HasValue.

而不是检查 ParentType Is Nothing