实体框架linq master详细投影到自定义类中

时间:2014-11-04 15:07:56

标签: c# vb.net linq entity-framework

我有一个Order类,其属性为" ID为Int64,Description为String,Details为List(Of OrderDetail)"
还有一个OrderDetail类,其属性为" ID为Int64,描述为字符串,数量为十进制"

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调用实体框架,并希望在每个订单上创建一个Order列表以及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()

问题似乎与此工作项有关 https://entityframework.codeplex.com/workitem/808

编辑:
Per UrbanEsc和jameslj我能够得到一些有效的代码 看来,如果Order.Details属性是" LIST"那么代码只有在使用时才有效:

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"然后我可以删除多余的" ToList"并使用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()

2 个答案:

答案 0 :(得分:1)

根据我的评论,您需要为详细信息上的SELECT添加.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

答案 1 :(得分:0)

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()