Я создаю динамический построитель отчетов, который позволяет пользователю выбирать поля из предопределенных классов (которые сопоставляются с таблицами базы данных через Entity Framework) в качестве фильтров для их данных. Чтобы создать запрос LINQ to Entities, я использую деревья выражений из-за динамического характера запросов. У меня он работает практически для всех нестандартных сценариев, но я действительно стараюсь заставить его работать для нескольких пользовательских сценариев.Expression Trees: Отфильтрованный подсчет по навигационной собственности
Сокращенный вариант моих моделей для одного из моих пользовательских запросов выглядит следующим образом:
public class Attendee {
public int ID { get; set; }
public DateTime? CancelledOn { get; set; }
[ForeignKey("Event")]
public int Event_ID { get; set; }
public virtual Event Event { get; set; }
}
public class Event {
public int ID { get; set; }
public virtual ICollection<Attendee> Attendees { get; set; }
}
Пример запроса, который пользователь хочет запустить, чтобы отфильтровать, чтобы показывать только те события, которые имеют более чем 10 Attendees, что не отменены. Если бы я писал это в нормальном IQueryable запроса, я хотел бы написать это как
db.Event.Where(s => s.Attendees.Count(a => a.CancelledOn == null) > 10);
с каркасной Expression Tree Я настройка, я могу справиться с «> 10» частью уже, но я не могу понять, как динамически генерировать часть «s.Attendees.Count (a => a.CancelledOn == null)». Я прочитал сообщения SO о том, как делать Count или Sum на свойстве верхнего уровня, но я не смог взломать любое из этих решений для работы с фильтрованным навигационным свойством. Пример сообщения: Dynamic LINQ, Select function, works on Enumerable, but not Queryable
Снимок экрана ниже - это пример другого фильтра, построенного с помощью деревьев выражений, чтобы вы могли увидеть пример того, что у меня есть. «pe» - это выражение ParameterExpression для типа, который передается в «Событие». «выражение» - это то, что я пытаюсь создать и оценить. http://grab.by/RoYm
LINQ запрос выше работает в
db.Event.Where(s=> s.StartDate >= '1/1/2016 12:00 am')
Любая помощь или направление на это было бы весьма признателен и, пожалуйста, дайте мне знать, если мне нужно, чтобы включить любые другие фрагменты кода.
Какой проект это? Если это MVC/Web API, вы должны действительно рассмотреть ODATA (я сделал то же самое, что вы делали некоторое время назад, оказалось, что это больно поддерживать). –
@SteveG, ASP.NET MVC. ODATA принимает строковые значения в качестве входов в фильтр, а также для выбора? Существуют сотни полей, которые пользователь может выбрать для фильтрации и отображения, а также могут создавать сложные фильтры с группировкой AND/OR'ing, всевозможные операторы (имеет значение null, пусто, равно, содержит, больше и т. Д. .). –
@ ZachFloyd: Да, именно для этого и предназначен ODATA. Вы можете создавать довольно сложные фильтры и выбирать только через строку запроса http, а реализация OData Web API будет применять их к IQueryables для вас. – StriplingWarrior