Linq: загрузка родительских и дочерних сущностей

Я пытаюсь загрузить данные из моей базы данных SQL Server 2008 в DTO на стороне сервера для передачи клиенту, и мне было интересно, как загрузить коллекции родительских и дочерних сущностей.

Из модели видно, что я пытаюсь загрузить всех пользователей и соответствующие UserRoles, которые объединены в таблице tblUsermmRole.

Когда я запускаю запрос Linq для сбоя при загрузке дочерних сущностей, запрос не может загрузить ни одного экземпляра в коллекцию.

Могу ли я загрузить эти сущности в одном запросе или мне следует загрузить пользователей в коллекцию, а затем итеративно создать дочерние AccessRoles?

Модель

введите описание изображения здесь

Объект передачи данных

Public Class User

    Public Property ID As Int32
    Public Property Username As String
    Public Property Password As String
    Public Property AccessRoles As IList(Of UserRoles)

End Class

Public Class UserRoles
    Public Property Role As ApplicationRole
End Class

Public Class ApplicationRole

    Public Property ID As Int32
    Public Property Description As String

End Class

Загрузка данных

Dim var = (From usr In ctx.tblUsers.OrderBy(Function(w) w.username)
              Join useraccess In ctx.tblUsermmRoles On usr.idUser Equals useraccess.idUser
              Join role In ctx.tblUserRoles On role.idRole Equals useraccess.idRole
                Select New User With {.ID = usr.idUser,
                                      .Username = usr.username,
                                      .Password = usr.pwd,
                                      .AccessRoles = New ApplicationRole With {.ID = role.idRole,
                                                                               .Description = role.description}}).ToList

Сообщение об исключении

{"Unable to cast the type 'Epms.Ui.Models.ApplicationRole' to type 'System.Collections.Generic.IList`1'. LINQ to Entities only supports casting EDM primitive or enumeration types."}

Трассировка стека

   at System.Data.Objects.ELinq.ExpressionConverter.ValidateAndAdjustCastTypes(TypeUsage toType, TypeUsage fromType, Type toClrType, Type fromClrType)
   at System.Data.Objects.ELinq.ExpressionConverter.GetCastTargetType(TypeUsage fromType, Type toClrType, Type fromClrType, Boolean preserveCastForDateTime)
   at System.Data.Objects.ELinq.ExpressionConverter.CreateCastExpression(DbExpression source, Type toClrType, Type fromClrType)
   at System.Data.Objects.ELinq.ExpressionConverter.ConvertTranslator.TranslateUnary(ExpressionConverter parent, UnaryExpression unary, DbExpression operand)
   at System.Data.Objects.ELinq.ExpressionConverter.UnaryTranslator.TypedTranslate(ExpressionConverter parent, UnaryExpression linq)
   at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
   at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
   at System.Data.Objects.ELinq.ExpressionConverter.MemberInitTranslator.TypedTranslate(ExpressionConverter parent, MemberInitExpression linq)
   at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
   at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
   at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.JoinTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)
   at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)
   at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)
   at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
   at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
   at System.Data.Objects.ELinq.ExpressionConverter.Convert()
   at System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption)
   at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
   at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
   at System.Data.Entity.Internal.Linq.InternalQuery`1.GetEnumerator()
   at System.Data.Entity.Infrastructure.DbQuery`1.System.Collections.Generic.IEnumerable<TResult>.GetEnumerator()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Epms.Ui.DataProvider.DataAccess.EntityProvider.GetUsers() in C:\Users\phil.murray\Desktop\Data Provider\Epms.Ui.DataProvider\DataAccess\EntityProvider.vb:line 24
   at Epms.Ui.DataProvider.DataProvider.VB$StateMachine_0_GetUsers.MoveNext() in C:\Users\phil.murray\Desktop\Data Provider\Epms.Ui.DataProvider\DataProvider.vb:line 27

person Phil Murray    schedule 02.09.2013    source источник
comment
Мой VB не очень хорош, так что это может быть совершенно неправильный синтаксис, но как насчет чего-то вроде .AccessRoles = New List(Of ApplicationRole) From { New ApplicationRole With {.ID = role.idRole, .Description = role.description}}?   -  person Joachim Isaksson    schedule 02.09.2013
comment
Это дает мне еще одно исключение - невозможно привести тип System.Collections.Generic.List1' to type 'System.Collections.Generic.IList1. LINQ to Entities поддерживает только приведение примитивов EDM или перечислимых типов.   -  person Phil Murray    schedule 02.09.2013


Ответы (1)


В конце концов я перешел на класс UserRoles, чтобы хранить значения ID int.

Public Class UserRoles
    Public Property Role As int32
End Class

Затем загрузил данные с помощью запроса Linq ниже.

Return (From usr In ctx.tblUsers.Include("tblUsermmRoles")
          Select New User With {.ID = usr.idUser,
                                .Username = usr.username,
                                .Password = usr.pwd,
                                .AccessRoles = usr.tblUsermmRoles.Select(Function(r) r.idRole)}).ToList
person Phil Murray    schedule 03.09.2013
comment
Ваш первоначальный подход был излишне внутренним (и не мог учесть реальность IList). Приятно, что вы опубликовали очень правильный код. В любом случае это не является точным решением вашего исходного вопроса (почему я получаю эту ошибку?). До сих пор не уверен, почему написанное мной решение (которое отвечало на ваш исходный вопрос) не сработало на вашем компьютере; но что ж ... важно то, что, в конце концов, все сделано правильно. - person varocarbas; 03.09.2013