Как лучше всего настроить контроллер для сортировки по многим (возможно, нулевым) критериям? Скажем, например, я создавал сайт по продаже автомобилей. В My CarController есть функция Index (), которая возвращает список автомобилей в виде списка, и сведения о каждой машине отображаются с частичным представлением.

Как лучше всего это структурировать? Особенно, если критериев много: тип автомобиля (он же внедорожник), марка автомобиля, модель автомобиля, год автомобиля, цена автомобиля, цвет автомобиля, bool IsNew, или если я хочу отсортировать по ближайшему ко мне и т. Д. m, используя NHibernate в качестве ORM. Должен ли я иметь всего тонну возможных запросов NHibernate и выяснить, какой из них выбрать, основываясь на if / then в контроллере? Или есть способ попроще.

Большое спасибо за помощь.

2
Solomon 9 Мар 2010 в 03:08

2 ответа

Лучший ответ

У меня есть задачи в системе и я создал специальный класс для поиска:

public class TaskSearchCriteria
{
    public List<int> Statuses { get; set; }
    public List<int> Severities { get; set; }
    public List<int> CreatedBy { get; set; }
    public List<int> ClosedBy { get; set; }
    public List<int> LastModificationBy { get; set; }

    public DateTime? CreationDateFrom { get; set; }
    public DateTime? CreationDateTo { get; set; }

    public bool SearchInComments { get; set; }
    public bool SearchInContent { get; set; }
    public bool SearchInTitle { get; set; }
}

Один из методов этого класса применяет фильтры:

public IQueryable<Task> Filter(IQueryable<Task> tasks)
{
    return
        FilterDates(
        FilterAssignedTo(
        FilterGroups(
        FilterOperationSystems(
        FilterPlatforms(
        FilterPriorities(
        FilterSeverities(
        FilterVersionsResolved(
        FilterVersionsReported(
        FilterTaskContent(
        FilterStatuses(tasks)))))))))));
}

Это один из методов, используемых для фильтрации:

private IQueryable<Task> FilterSeverities(IQueryable<Task> tasks)
{
    if (Severities.Contains(TaskSearchConsts.All) || (!Severities.Any()))
        return tasks;

    var expressions = new List<Expression>();

    if (Severities.Contains(TaskSearchConsts.Active))
        expressions.Add(_taskParameter.EqualExpression("Severity.IsActive", 1));

    return tasks.WhereIn(_taskParameter, "Severity.ID", Severities, expressions);
}

Это Entity Framework, но это можно легко сделать и в nHibernate, добавив в IQuery предложения where.

Для поиска у меня есть метод в контроллере:

[HttpPost]
public ActionResult TaskSearch([Bind(Prefix = "Search")]TaskSearchCriteria criteria)

Наличие одного класса для фильтрации - это хорошо, потому что его можно сериализовать и сохранить в базе данных для использования в будущем. Таким образом, пользователь может повторно использовать параметры фильтра.

Вам придется:

public class CarSearchCriteria
{
    List<int> ListOfCarTypesIds;
    List<int> ListOfCarBrandIds;
    bool IsNew;
    //and more
}

Если список пуст, вы не применяете фильтр.

1
LukLed 9 Мар 2010 в 03:43

Если у вас много критериев, я считаю, что лучше инкапсулировать в класс, а не передавать множество параметров действия. Например, у проекта, над которым я сейчас работаю, есть действие со следующей подписью:

public claass JobsController : Controller 
{
    public IList<JobDto> Index(JobSearchCriteria criteria)
    { 
        IList<JobDto> jobs = _jobs.Find(criteria);
        //... 
    }
}

Метод репозитория просто проходит через критерии построения IQueryable по мере его продвижения. Этот конкретный проект использует Linq To Sql, но тот же принцип может применяться с использованием NHibernates Criteria API (или Linq to NH).

0
richeym 9 Мар 2010 в 03:28