У меня есть класс Order со свойствами "ID как Int64, Description as String, Details as List (Of OrderDetail)"
Существует также класс OrderDetail со свойствами "ID как Int64, Description as String, Amount as 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
Затем я создал статическую/общую функцию для вызова Entity Framework с использованием 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.
ЗАМЕТКА:
Это проблема Entity Framework, а не проблема 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
РЕДАКТИРОВАТЬ:
Ну, это безумие. Проблема, похоже, связана с проблемой VB.NET с EF.
Эта версия С# работает.
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
РЕДАКТИРОВАТЬ:
В 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", тогда я могу удалить дополнительный "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()
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()
Согласно моему комментарию, вам нужно добавить.ToList() для вашего SELECT on Details.
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[[OrderDetails]]' to type 'System.Collections.Generic.IEnumerable
1 [[OrderDetails]] '. LINQ to Entities поддерживает только приведение типов примитивов EDM или перечислений."
1[[OrderDetail]]' to type 'System.Collections.Generic.ICollection
1 [[OrderDetail]]'. LINQ to Entities поддерживает только приведение типов примитивов или перечислений EDM «.