Создание динамических запросов со структурой сущности - PullRequest
39 голосов
/ 04 апреля 2011

Я хотел бы знать, каков наилучший способ создания динамических запросов с помощью Entity Framework и Linq.

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

Я оглянулся и увидел, что могу динамически создать строку, которая может быть выполнена в конце моего метода.Мне не очень нравится этот способ.Есть лучший способ сделать это?Желательно типа safe с проверкой компиляции?

Ответы [ 4 ]

54 голосов
/ 04 апреля 2011

Вы можете составить IQueryable<T> шаг за шагом.Предполагая, что у вас есть класс FilterDefinition, который описывает, как пользователь хочет фильтровать ...

public class FilterDefinition
{
    public bool FilterByName { get; set; }
    public string NameFrom { get; set; }
    public string NameTo { get; set; }

    public bool FilterByQuantity { get; set; }
    public double QuantityFrom { get; set; }
    public double QuantityTo { get; set; }
}

... тогда вы можете построить запрос следующим образом:

public IQueryable<SomeEntity> GetQuery(FilterDefinition filter)
{
    IQueryable<SomeEntity> query = context.Set<SomeEntity>();
    // assuming that you return all records when nothing is specified in the filter

    if (filter.FilterByName)
        query = query.Where(t => 
            t.Name >= filter.NameFrom && t.Name <= filter.NameTo);

    if (filter.FilterByQuantity)
        query = query.Where(t => 
            t.Quantity >= filter.QuantityFrom && t.Quantity <= filter.QuantityTo);

    return query;
}
32 голосов
/ 04 апреля 2011

Единственный известный мне способ - это создать IQueryable на основе ваших фильтров.

    public List<Contact> Get(FilterValues filter)
    {
        using (var context = new AdventureWorksEntities())
        {
            IQueryable<Contact> query = context.Contacts.Where(c => c.ModifiedDate > DateTime.Now);

            if (!string.IsNullOrEmpty(filter.FirstName))
            {
                query = query.Where(c => c.FirstName == filter.FirstName);
            }

            if (!string.IsNullOrEmpty(filter.LastName))
            {
                query = query.Where(c => c.LastName == filter.LastName);
            }

            return query.ToList();
        }
    }
6 голосов
/ 26 августа 2015

Я создал универсальный репозиторий , который должен вам помочь. Он поддерживает единый API для запроса и сортировки как по известным, так и по динамическим полям:

       //Filter on known fields
       var keyboard = Query<Product>.Create(p=>p.Category=="Keyboard");
       var keyboards = repository.Get(keyboard);

       //Or filter on dynamic fields
       var filter = Query<Product>.Create("Rating", OperationType.GreaterThan, 4)
       var filteredKeyboards = repository.Get(filter);

       //You can also combine two queries togather
       var filterdKeyboards2 = repository.Get(keyboard.And(filter))

       //Order it on known fields
       var orderedKeyboard = keyboard.OrderBy(o=>o.Asc(p=>p.Name));
       var orderedKeyboards = repository.Get(orderedKeyboard);

       //Or order by on dynamic fields
       var userOrdering = keyboard.OrderBy(o=>o.Asc("Name"));
       var orderedKeyboards2 = repository.Get(userOrdering);

Я не знаю, какой объект поиска / DTO вы получаете, но вы можете легко создать общий объект поиска / DTO и сопоставить его с объектом Query в несколько строк кода. В прошлом я использовал его для службы WCF, и он работал очень хорошо для меня.

1 голос
/ 04 апреля 2011

Вы можете изучить создание службы с использованием WCF Data Services и динамически создать URI для запроса модели вашей сущности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...