C# 实体框架linq主细节到自定义类的投影

C# 实体框架linq主细节到自定义类的投影,c#,vb.net,linq,entity-framework,C#,Vb.net,Linq,Entity Framework,我有一个Order类,其属性ID为Int64,描述为String,详细信息为ListOf OrderDetail 还有一个OrderDetail类,其属性ID为Int64,描述为String,金额为Decimal Public Class Order Property ID As Int64 Property Description As String Property Details As List(Of OrderDetail) End Class Public C

我有一个Order类,其属性ID为Int64,描述为String,详细信息为ListOf OrderDetail 还有一个OrderDetail类,其属性ID为Int64,描述为String,金额为Decimal

Public Class Order
    Property ID As Int64
    Property Description As String
    Property Details As List(Of OrderDetail)
End Class

Public Class OrderDetail
    Property ID As Int64
    Property Description As String
    Property Amount As Decimal
End Class
然后,我创建了一个静态/共享函数来使用LINQ调用实体框架,并希望创建一个订单列表以及每个订单上的OrderDetails

Public Shared Function GetOrders() As List(Of Order)
    Dim db = New OrderEntities()

    Dim orders = (From O In db.OrderTable
    Select New Order With {
        .ID = O.OrderID,
        .Description = O.OrderDescription,
        .Details = (From OD In db.OrderDetailTable
            Where OD.OrderID = O.OrderID
            Select New OrderDetail With {
                .ID = OD.OrderDetailID,
                .Description = OD.OrderDetailDescription,
                .Amount = OD.OrderDetailAmount})
        }
    ).ToList()

    Return orders
End Function
执行时,我将得到以下错误

Unable to cast the type 'System.Linq.IQueryable`1[[OrderDetails]]' to type 
'System.Collections.Generic.List`1[[OrderDetails]]'. 
LINQ to Entities only supports casting EDM primitive or enumeration types.
注: 这是一个实体框架问题,而不是LINQ问题。 例如,在使用EF但不投影到新对象列表中时,以下操作可以正常工作

    Public Shared Function GetOrders() As Object
    Dim db = New OrderEntities()

    Dim orders = (From O In db.OrderTable
    Select New With {
        .ID = O.OrderID,
        .Description = O.OrderDescription,
        .Details = (From OD In db.OrderDetailTable
            Where OD.OrderID = O.OrderID
            Select New With {
                .ID = OD.OrderDetailID,
                .Description = OD.OrderDetailDescription,
                .Amount = OD.OrderDetailAmount})
        }
    ).ToList()

    Return orders
End Function
编辑: 这太疯狂了。问题似乎是EF的VB.NET问题。 这个C版本可以工作

var data = db.OrderTable
    .Select(O => new Order { ID = O.OrderID, 
    Description = O.OrderDescription,
    Details = db.OrderDetailTable.Where(D => D.OrderID == O.OrderID)
        .Select(OD => new OrderDetail { Description = OD.OrderDetailDescription})})
        .ToList();  
这在VB.NET中不起作用

Dim data = db.OrderTable
    .Select(Function(O) New Order With {.ID = O.OrderID, 
    .Description = O.OrderDescription,
    .Details = db.OrderDetailTable.Where(Function(D) D.OrderID = O.OrderID)
        .Select(Function(OD) New OrderDetail With {.Description = OD.OrderDetailDescription})})
        .ToList()
问题似乎与此工作项有关。

编辑: 根据UrbanEsc和jameslj,我能够得到一些工作代码。 似乎如果Order.Details属性是一个列表,那么代码只有在使用以下命令时才能工作:

Dim orders = (From O In db.OrderTable
    Select New With {
        .ID = O.OrderID,
        .Description = O.OrderDescription,
        .Details = (From OD In db.OrderDetailTable.AsEnumerable()
            Where OD.OrderID = O.OrderID
            Select New With {
                .ID = OD.OrderDetailID,
                .Description = OD.OrderDetailDescription,
                .Amount = OD.OrderDetailAmount}).ToList()
        }
    ).ToList()
请注意详细信息中的AsEnumerable和ToList。两者都是必需的。 但是如果我将Order.Details属性更改为IQueryable或IEnumerable,那么我可以删除额外的收费列表并使用AsQueryable或AsEnumerable

Property Details As IQueryable(Of OrderDetail)

Dim orders = (From O In db.OrderTable
    Select New With {
        .ID = O.OrderID,
        .Description = O.OrderDescription,
        .Details = (From OD In db.OrderDetailTable.AsQueryable()
            Where OD.OrderID = O.OrderID
            Select New With {
                .ID = OD.OrderDetailID,
                .Description = OD.OrderDetailDescription,
                .Amount = OD.OrderDetailAmount})
        }
    ).ToList()

根据我的评论,您需要为“选择详细信息”添加一个.ToList

Public Shared Function GetOrders() As List(Of Order)
    Dim db = New OrderEntities()

    Dim orders = (From O In db.OrderTable
    Select New Order With {
        .ID = O.OrderID,
        .Description = O.OrderDescription,
        .Details = (From OD In db.OrderDetailTable
            Where OD.OrderID = O.OrderID
            Select New OrderDetail With {
                .ID = OD.OrderDetailID,
                .Description = OD.OrderDetailDescription,
                .Amount = OD.OrderDetailAmount})
            .ToList()
        }
    ).ToList()

    Return orders
End Function

托利斯特不起作用。这返回了一个不同的错误。无法将类型“System.Linq.IQueryable1[[OrderDetails]]”强制转换为类型“System.Collections.Generic.IEnumerable1[[OrderDetails]]”。LINQ to Entities仅支持强制转换EDM基元或枚举类型。您发布的代码无效。我直接复制并粘贴了代码,当我运行代码时,我无法将类型“System.Linq.IQueryable1[[OrderDetails]]”转换为类型“System.Collections.Generic.IEnumerable1[[OrderDetails]]”。LINQ to实体仅支持强制转换EDM基元或枚举类型。您的代码非常接近。我使用了@jameslj代码,将您的代码从db.OrderDetailTable中的OD更改为db.OrderDetailTable.AsEnumerable中的OD,它可以正常工作。仍然需要代码中的所有ToList。然后用正确的代码回答您自己的问题,并将其标记为Answer此代码不起作用。它返回以下错误。无法将类型“System.Collections.Generic.List1[[OrderDetail]]”强制转换为类型“System.Collections.Generic.ICollection1[[OrderDetail]]”。LINQ to Entities仅支持强制转换EDM基元或枚举类型。抱歉,您的代码不起作用。我已将Details属性更改为集合,而它本应是列表。
orders = db.OrderTable.Select(Function(x) New Order() With 
    {.Id = x.OrderID,
            .Description = x.OrderDescription,
            .Details = db.OrderDetailTable.Where(
                Function(y) y.OrderId = x.OrderID).ToList().Select(
                    Function(z) New OrderDetail() With
                        {.Id = z.OrderDetailId,
                         .Description = z.OrderDetailDescription,
                         .Amount = z.OrderDetailAmount}).ToList()}).ToList()