ASP.Net MVC - невозможно преобразовать результат запроса LINQ в ViewModel

Я пытаюсь связать элемент управления меню в виде дерева в частичном представлении с ViewModel. Я создал вложенную модель представления, предполагая, что это правильный способ одновременно переносить все вложенные данные, необходимые для меню дерева навигации, и поэтому я написал свой запрос linq для извлечения данных во вложенном режиме. Как новичок, я не уверен на 100%, что это правильный способ. Я пытаюсь связать свою модель представления с результатом запроса Linq. Моя модель вложена, как и мой запрос Linq. Я столкнулся с трудностями при соединении этих двух вместе. Каким бы способом я ни пытался, я получаю ошибку приведения типа, например, не могу преобразовать из Type IQueriable в IList коллекций. Мой код:

        // ViewModel
namespace My.Namespace
{
    public class MyViewModel
    {
        public decimal CategoryID { get; set; }
        public string CategoryName { get; set; }
        public decimal Badge { get; set; }
        public IList<SubCategories> CategorySubCategories { get; set; }
    }
    public class SubCategories
    {
        public decimal SubCategoryID { get; set; }
        public string SubCategoryName { get; set; }
        public decimal Badge { get; set; }
        public List<Items> SubCategoryItems { get; set; }
    }
    public class Items
    {
        public decimal ID { get; set; }
        public string ItemName { get; set; }
        public List<SubItems> SubItems { get; set; }
    }
    public class SubItems
    {
        public decimal ID { get; set; }
        public string SubItemName { get; set; }
    } 
}


//Databinding code:

    MyViewModel result = new MyViewModel();
            var query= (List<MyViewModel>)(from c in dbContext.TableName
                         where c.CHILD_ID == 0
                         select new MyViewModel
                         {
                             CategoryID = c.ELEMENT_ID,
                             CategoryName = c.CHILD_DESC,
                             CategorySubCategories = (List<SubCategories>)(from s in dbContext.TableName
                                                                           where s.PARENT_ID == c.ELEMENT_ID
                                                                           select new SubCategories
                                                                           {
                                                                               SubCategoryID = s.ELEMENT_ID,
                                                                               SubCategoryName = s.CHILD_DESC,
                                                                               SubCategoryItems = (List<Items>)(from i in dbContext.TableName
                                                                                                                where i.PARENT_ID == s.ELEMENT_ID
                                                                                                                select new Items
                                                                                                                {
                                                                                                                    ID = i.ELEMENT_ID,
                                                                                                                    ItemName = i.CHILD_DESC
                                                                                                                }
                                                                                                   )
                                                                           }
                                                                           )
                         });

return query.toList();

Я получаю сообщение об ошибке @ line: var query = (List) (from c in dbContext.TableName Error: Невозможно привести объект типа 'System.Data.Entity.Infrastructure.DbQuery1[MyViewModel]' to type 'System.Collections.Generic.List1 [MyViewModel]'.


person Hasteq    schedule 10.04.2014    source источник
comment
Попробуйте добавить ToList () в конец оператора select.   -  person Andrei Dvoynos    schedule 10.04.2014
comment
@Andrei, я сделал это и получил ту же ошибку: невозможно привести тип System.Linq.IQueryable1' to type 'System.Collections.Generic.List1. LINQ to Entities поддерживает только приведение примитивов EDM или перечислимых типов.   -  person Hasteq    schedule 10.04.2014
comment
Я попробовал этот var query = удалил приведение на верхнем уровне и все подуровни добавил .ToList () на всех уровнях и получил следующую ошибку: LINQ to Entities не распознает метод 'System.Collections.Generic.List1[SubCategories] ToList[SubCategories](System.Collections.Generic.IEnumerable1 [SubCategories] ) ', и этот метод нельзя преобразовать в выражение хранилища.   -  person Hasteq    schedule 10.04.2014


Ответы (1)


В вашей модели представления измените типы списков на типы IEnumerable. Убедитесь, что вы не используете метод расширения .ToList () для этих подвыборок.

Результирующие типы ваших подчиненных операторов выбора не являются экземплярами List, но реализуют интерфейс IEnumerable. Они могут реализовывать ICollection, IList и т. Д., Но вы можете поиграть с этим.

person Nathan A    schedule 10.04.2014
comment
Я пошел дальше и изменил List ‹› на IEnumerable ‹› в моей модели просмотра. Моя реализация выглядит так: MyViewModel result = new MyViewModel (); result = (из c в dbContext.TableName, где c.CHILD_ID == 0 выберите новую ToolNavigationViewModel {CategoryID = c.ELEMENT_ID, CategoryName = c.CHILD_DESC, CategorySubCategories = (IEnumerable ‹SubCategories›) (из s в dbContext.TableName ... .................. Но по-прежнему появляется ошибка приведения - person Hasteq; 10.04.2014
comment
Предлагаете ли вы следующие шаги: 1. Измените List ‹› на IEnumerable ‹› в классах модели просмотра 2. Выполните преобразование основного запроса и подзапросов с помощью соответствующих Ienumerables ViewModel, таких как: result = (IEnumerable ‹MyViewModel›) (от c в dbContext.TableName ..//sub query (IEnumerable ‹SubCategories›) (из s в dbContext.TableName ...); но это не помогает .. Мне здесь не хватает чего-то базового .. - person Hasteq; 10.04.2014
comment
Как вы думаете, поможет ли объединение вложенной виртуальной машины и модели? - person Hasteq; 11.04.2014
comment
Если он настроен правильно, вам вообще не нужно выполнять какое-либо явное приведение с запросом LINQ. Удалите ВСЕ явные приведения в запросе LINQ. Изменения, которые я предлагал, касались только модели представления. Сделайте свой список ‹T› участников IEnumberable ‹T› участников. - person Nathan A; 11.04.2014
comment
Здорово ! Спасибо. Я пошел дальше и изменил весь список на виртуальных машинах, поскольку IEnumerable удалил ToList () во вспомогательных запросах, удалил все приведение типов. Это сработало. Огромное спасибо - person Hasteq; 11.04.2014
comment
может указать на статью или любой учебный источник, где я могу пояснить концепции, связанные с привязкой запросов Linq к классам коллекции / виртуальным машинам и связанным функциям структуры данных и совместимости. заранее спасибо - person Hasteq; 11.04.2014
comment
просто любопытно узнать ... Я пробовал то же решение раньше, но с той лишь разницей, что я использовал List вместо IEnumerable в своих ViewModels и столкнулся с множеством проблем. Как IEnumerable решил всю проблему - person Hasteq; 11.04.2014
comment
Это не так сложно, но очень многословно, поэтому я постараюсь уместить все это здесь. Во-первых, обратите внимание, что тип возвращаемого значения метода SELECT - это IQueryable {T}, который наследует IEnumerable {T}. При использовании LINQ-to-Entities (или LINQ-to-SQL) SELECT возвращает неизвестный экземпляр. Вы не можете предполагать, что знаете, что это такое, но можете предположить, что это НЕ экземпляр класса List {T}, поэтому ваше преобразование и исходный код не удалось. Экземпляр, возвращаемый SELECT, неявно является IEnumerable {T}, поэтому он отлично работает с вашей модифицированной моделью представления. Надеюсь, это поможет. - person Nathan A; 11.04.2014
comment
И чтобы ответить на ваш предыдущий вопрос, у вас проблемы не столько с частью LINQ. Это более простой, чем это. Источников по этим темам очень много. В частности, вы хотите разобраться в различиях между классами и интерфейсами, повышающим и понижающим преобразованием, неявным / явным приведением и наследованием. Вы можете стереть каждый LINQ в своем примере, и у вас все равно будут проблемы, если вы попытаетесь преобразовать экземпляр интерфейса в класс, который ваш экземпляр не поддерживает. - person Nathan A; 11.04.2014
comment
Большое спасибо за ваши предложения. Я думаю, что мне нужно углубить свое понимание структуры данных C # - person Hasteq; 16.04.2014
comment
Я собираюсь изучить эту грубую информацию на PluralSight -C # Collections Fundamentals: pluralsight.com/ обучение / Курсы / TableOfContents / Если у вас будет возможность, пожалуйста, ваше предложение. Еще раз спасибо - person Hasteq; 16.04.2014
comment
Не знаю, поможет ли это. Это касается коллекций, но не базовых основ C #, что, как я считаю, могло бы помочь. - person Nathan A; 16.04.2014