0

I'm having an issue retrieving correct result from database using Entity Framework Core.

Here is my Article table:

enter image description here

I would like to create dynamic filter using IQueryable that will return the following results:

Select a.Id, a.Name, a.BrandId, a.GenderId
from dbo.Articles a
where GenderId in (1)
  and BrandId in (1, 2, 3)

which returns:

enter image description here

This is my controller action:

public async Task<IActionResult> Clothes()
{
    var model = new ArticleFilterViewModel();
    model.Genders.AddRange(new int[1] { 1 });
    model.Brands.AddRange(new int[3] { 1, 2, 3 });
    var result = await articleSerivce.GetFilteredUsers(model);
    return View(result);
}

Here is my repository method for fetching filtered articles:

public ICollection<Article> GetFilteredUsers(ArticleFilter filter)
{
    var articles = GetAll();
    articles = FilteredByBrand(articles, filter.Brands);
    articles = FilteredByGender(articles, filter.Genders);
    var result = articles.ToList();
    return result;
}

IQueryable<Article> FilteredByBrand(IQueryable<Article> articles,  List<int> items)
{
    return articles.WhereIf(items.IsNotNullOrEmpty(),  x => items.Contains(x.BrandId));
}

IQueryable<Article> FilteredByGender(IQueryable<Article> articles, List<int> items)
{
     return articles.WhereIf(items.IsNotNullOrEmpty(), x => items.Contains(x.GenderId));
}

After this code is executed I get the following:

enter image description here

I get 3 articles as a result instead of 2 (Article Id's: 2,3,2).

Any idea what I'm doing wrong?

6
  • Looks ok to me. So you are getting objects with duplicate PK (2,3,2)? Sounds weird. Commented Aug 23, 2018 at 9:41
  • Yes. This is what bothers me Commented Aug 23, 2018 at 10:51
  • Can you provide a repro project, so we can take a look? Commented Aug 23, 2018 at 11:01
  • @Ivan Stoev Where would you like me to send you zip file? Commented Aug 23, 2018 at 11:40
  • You can provide a public downloadable link in your question (Dropbox, OneDrive, GitHub etc.) Commented Aug 23, 2018 at 11:43

2 Answers 2

1

I dont know what your WhereIf() method do or what your really get from GetAll() but if I replace WhereIf() by Where() it works as expected.

private IQueryable<Article> FilteredByBrand(IQueryable<Article> articles, List<int> items)
{
    return items.IsNullOrEmpty() ? articles : articles.Where(x => items.Contains(x.BrandId));
}

private IQueryable<Article> FilteredByGender(IQueryable<Article> articles, List<int> items)
{
    return items.IsNullOrEmpty() ? articles : articles.Where(x => items.Contains(x.GenderId));
}

Returns

2 - Cool t-shirt - 2 - 1
3 - Yellow panties - 3 - 1

Here is my complete repro code.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. It seams that problem is in WhereIf function. ' public static IQueryable<TSource> WhereIf<TSource>(this IQueryable<TSource> source, bool condition, Func<TSource, bool> predicate) { if (condition) return source.Where(predicate).AsQueryable(); else return source; } '
@user3569465 Then apparently it's wrong. I was expecting it to be public static IQueryable<TSource> WhereIf<TSource>(this IQueryable<TSource> source, bool condition, Expression<Func<TSource, bool>> predicate) { return condition ? source.Where(predicate) : source; }. Note the Expression<Func<…>> - never use Func<..> with IQueryable<T>.
1

With EF Core, try this.

Simple and performatic dynamic filter

public static List<Inventory> GetAll(string po, string cod)
{
    using (var context = new ApplicationDbContext())
    {
        var Items = context.Inventorys
            .Where(p => p.CodigoPO == po || po == string.Empty)
            .Where(p => p.CodigoProduto == cod || cod == string.Empty).ToList();
        return Items;
    }
}

Generated by EF Core, using only the PO parameter Generated by EF Core, using only the PO parameter

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.