Filtering data on basis of attribute values I am writing code to filter data on basis of attribute values. It is possible that the user can select multiple values.

How can this be better?

Models.Products filter(ViewModel.Filter search,IEnumerable&lt;Models.Products&gt; product)
{
    if (search.filter!= null &amp;&amp; search.filter.Count&gt;0)
        {
             var f = search.First();
             var tempProducts = products
                               .Where(c =&gt; c.productattributes
                                            .Where(a =&gt; a.AttributeId == f.Id &amp;&amp; f.Value.Contains(a.Value))
                                            .Any());
             search.filter.Remove(f);
             foreach (var fs in search)
             {
                var p = products.Where(c =&gt; c.productattributes.Where(a =&gt; a.AttributeId == fs.Id &amp;&amp; fs.Value.Contains(a.Value)).Any());
                tempProducts = tempProducts.Union(p);
             }
             products = tempProducts;
        }
}


Filter View Model:

public class Filters
{
    public long Id { get; set; }

    public IEnumerable&lt;string&gt; Value { get; set; }
}
Your code appears to be incomplete but I've provided some ideas below.

Filters Class

I'm looking at your Filters class:


public class Filters
{
    public long Id { get; set; }
    public IEnumerable&lt;string&gt; Value { get; set; }
}



From this, I am assuming that the purpose of this is to hold the Attribute Id (key) and Search Keywords (value). So, I would propose you just use a Dictionary&lt;long, List&lt;string&gt;&gt; -- note that I changed the type of your Search Keywords to a List as I am not seeing any reason within your code example as to why it should/would need to be an IEnumberable type.

That would then change the method:


Method renamed
Parameter updated to use Dictionary instead (per above)


Here is the updated method

public IEnumerable&lt;Product&gt; FilterProductsByAttributeId(
    Dictionary&lt;long, List&lt;string&gt;&gt; filters,
    IEnumerable&lt;Product&gt; products)
{
    // your method contents here
}




Filter Method

I'm not sure why you have a complicated initializer for your tempProducts, but maybe it can be improved to something like this?

public IEnumerable&lt;Product&gt; FilterProductsByAttributeId(Dictionary&lt;long, List&lt;string&gt;&gt; filters, IEnumerable&lt;Product&gt; products)
{
    if (products == null) throw new ArgumentNullException(nameof(products));
    if (filters == null) throw new ArgumentNullException(nameof(filters));

    IEnumerable&lt;Product&gt; result = new List&lt;Product&gt;();
    foreach (var f in filters)
    {
        result = result.Union(products.Where(p =&gt; p.ProductAttributes
            .Where(a =&gt; a.AttributeId == f.Key &amp;&amp; f.Value.Contains(a.Value)).Any()));
    }

    return result;    
}


Alternatively you can use the Aggregate extension:

return 
    filters
        .Aggregate(
            new List&lt;Product&gt;(), 
            (current, next) =&gt; current.Union(..)
        );