Jak filtrować po dynamicznej liczbie warunków?

0

Cześć,

Mam dynamiczną listę parametrów (warehouse_id, item_name, item_id, create_date) Użytkownik może chcieć filtrować dane po jednym lub więcej parametrów. Jak w klauzurze where zbudować warunki filtrowania opcjonalnych danych, na przykład jeśli user poda warehouse_id, warunek uwzględnia go, jeśli przekaże null filtrowanie danych po tym kluczu jest pomijane. Dla pozostałych kuczy podobnie.

0

Możesz sprawdzić IQueryable i deferred execution.
Idziesz po tych wartość i jeśli są one podane to dodajesz kolejne filtry (where), a na końcu egzekwujesz

2

Jabym chyba w ten sposób przekazał warunki do IQueryable

var result = ApplyFilters(data, filters);

foreach (var item in result)
{
     Console.WriteLine($"WarehouseId: {item.WarehouseId}, ItemName: {item.ItemName}, ItemId: {item.ItemId}, CreateDate: {item.CreateDate}");
}

public static List<T> ApplyFilters<T>(IEnumerable<T> data, List<Filter<T>> filters)
{
    IQueryable<T> query = data.AsQueryable();

    foreach (var filter in filters)
    {
        query = query.Where(filter.Condition);
    }

    return query.ToList();
}

public class Filter<T>
{
    public Func<T, bool> Condition { get; set; }

    public Filter(Func<T, bool> condition)
    {
        Condition = condition;
    }
}

// Poprawka tak jak Saalin wspomniał
query = query.Where(t => filter.Condition(t));
0

Dokładnie tak. Dla każdego filtra dodajemy warunek Where dla Queryable i dopiero po tym wszystkim materializacja

1

Dokładnie nie. Przede wszystkim IQueryable<T>.Where nie przyjmuje jako argument Func<T, bool>, a użycie AsQueryable to sztuka dla sztuki, a nie deferred execution.

1

Wystarczy odrobina logiki boolowskiej i minuta na napisanie warunków, tym bardziej, że jest ich 4 a nie milion.

IEnumerable<Model> Filter(IEnumerable<Model> data, Filter filter)
{
    return data
        .Where(x => filter.warehouse_id == null || x.warehouse_id == filter.warehouse_id)
        .Where(x => filter.item_name == null || x.item_name == filter.item_name)
        .Where(x => filter.item_id == null || x.item_id == filter.item_id)
        .Where(x => filter.create_date == null || x.create_date == filter.create_date);
}

public class Model
{
    public int warehouse_id { get; set; }
    public string item_name { get; set; }
    public int item_id { get; set; }
    public DateTime create_date { get; set; }
}

public class Filter
{
    public int? warehouse_id { get; set; }
    public string item_name { get; set; }
    public int? item_id { get; set; }
    public DateTime? create_date { get; set; }
}

Można ewentualnie napisać extension enkapsulujący logikę w stylu WhereNotNull.

1 użytkowników online, w tym zalogowanych: 0, gości: 1