Entity Framework 4.0 - возвращаемый список объектов модели + количество дочерних элементов на объект

В моем проекте у меня общая потребность вернуть коллекции объектов моей модели, а также количество определенных типов дочерних объектов в каждом, но я не знаю, возможно ли это и как смоделировать свойство TotalCount в класс модели и заполнить его как часть одного запроса Entity Framework, предпочтительно с использованием запросов LINQ. Возможно ли это сделать, используя Entity Framework .Include («Object») и .Skip () и .Take ()? Я новичок в Entity Framework, поэтому мне может не хватать множества очевидных вещей, которые могут позволить это ...

Я также хотел бы иметь возможность разбивать на страницы динамически создаваемые свойства count. Я думаю, что наиболее масштабируемым подходом было бы хранить счетчики как отдельные свойства базы данных, а затем просто запрашивать свойства счетчика. Но для случаев, когда я имею дело с небольшим количеством строк, я бы предпочел вести подсчет динамически.

В такой модели:

Таблица: Класс

Стол: Профессор

Таблица: Участник

Таблица: ClassComment

Я хотел бы вернуть список объектов класса в форме List, но я также хотел бы, чтобы количество посетителей и комментариев класса определялось в одном запросе (предпочтительно LINQ) и устанавливалось в двух свойствах класса, называемых AttendeeCount и ClassCommentCount. .

У меня пока есть это:

var query = from u in context.Classes
            orderby tl.Name
            select u;

List<Class> topics = ((ObjectQuery<Class>)query)
    .Include("ClassComments")
    .Skip(startRecord).Take(recordsToReturn).ToList();

Любые предложения или альтернативные подходы к запросам, которые все еще позволяют использовать .Include () и разбиение на страницы, были бы очень признательны, чтобы создать единый запрос к базе данных, если это вообще возможно. Спасибо за любые предложения!


person Shan Plourde    schedule 13.02.2011    source источник


Ответы (2)


Попробуй это:

public class ClassViewModel {
    public Class Class { get; set; }
    public int AttendeeCount { get; set; }
    public int ClassCommentCount { get; set; }
}


var viewModel = context.Classes.Select(clas => 
    new ClassViewModel { 
        Class = clas, 
        AttendeeCount = clas.ClassAttendes.Count, 
        ClassCommentCount = clas.ClassComments.Count}
).OrderBy(model => model.ClassCommentCount).Skip(startRecord).Take(recordsToReturn).ToList();

Для подсчета необязательно включать комментарии.

person LukLed    schedule 13.02.2011
comment
Спасибо LukLed, ваше предложение похоже на предложение Ладислава. Я попробую такой подход. Но я все еще не уверен в одном: можно ли упорядочить записи, проецируемые на анонимный тип, с помощью свойств count перед применением разбивки на страницы? - person Shan Plourde; 13.02.2011

Так не пойдет. Самый простой подход - использовать проекцию в анонимный (или настраиваемый) не сущностный тип. Я бы попробовал что-то вроде этого:

var query = context.Classes
              .Include("ClassComments")  // Only add this if you want eager loading of all realted comments
              .OrderBy(c => c.Name)
              .Skip(startRecord)
              .Take(recordsToReturn)
              .Select(c => new 
                 {
                   Class = c,
                   AttendeeCount = c.Attendees.Count(),
                   ClassCommentCount = c.ClassComments.Count() // Not needed because you are loading all Class comments so you can call Count on loaded collection
                 });

Проблема в вашем требовании - это свойства AttendeeCount и ClassCommentCount. Вы не можете легко добавить их в свою модель, потому что в базе данных нет соответствующего столбца (если вы не определите его, и в этом случае вам не нужно вручную подсчитывать записи). Вы можете определить их в частичной реализации класса, но в таком случае вы не можете использовать их в запросе Linq-to-entity.

Единственный способ сопоставить это в EF - использовать представление DB и создать специальный объект только для чтения, чтобы представить его в вашем приложении, или использовать DefiningQuery, который представляет собой настраиваемую команду SQL, определенную в SSDL вместо таблицы или представления БД.

person Ladislav Mrnka    schedule 13.02.2011
comment
Похоже, я придерживался идеи о необходимости возвращать мои необработанные экземпляры класса Entity, но я попробую этот подход. Если мне нужно реализовать разбиение на страницы EF на основе этих свойств счетчика, должны ли эти свойства быть столбцами базы данных или представлением базы данных? Спасибо - person Shan Plourde; 13.02.2011
comment
@Shan: Я не уверен, о чем вы просите. Вам не нужно постоянно подсчитывать количество хранилищ, чтобы иметь возможность разбивать на страницы. Пагинация осуществляется функцией Skip and Take, и вы обязаны передать ей правильные значения. Счетчик обычно используется только для создания некоторого пейджера в пользовательском интерфейсе и показывает, сколько элементов на самом деле находится в БД. - person Ladislav Mrnka; 13.02.2011
comment
Я понимаю, что постоянное хранение общих подсчетов не является обязательным условием для реализации разбивки на страницы, я просто не был уверен, возможно ли реализовать разбиение на страницы в проекции LINQ to entity framework с динамическими значениями подсчета, хотя LukLed указал, что это так (я я новичок в EF). - person Shan Plourde; 13.02.2011
comment
Что касается сохранения счетчиков в базе данных по сравнению с динамическим определением, я не уверен, существует ли когда-либо критическая массовая ситуация, которая могла бы выиграть от хранения общих счетчиков в базе данных, чтобы избежать полного сканирования таблицы для каждого запроса на разбиение на страницы. ... т.е. что, если у вас есть миллионы строк и несколько типов пользовательских агентов, таких как Интернет, iPhone, Android и т. был хотя за сохраняющимся счетчиком для целей пейджинга. - person Shan Plourde; 13.02.2011