-2

Can I and how would I pass an array of strings to a Linq query, so that the elements of the array feed the Where clause, like in example below?

If one of arrays is empty, the query should still work (just ignore the respective where clause).

Would the query change if instead of array one passess e.g. a list like List<string> brands, List<string> categories etc.?

    private IEnumerable<LatestReading> getLatestReadings(string[] brands, string[] categories)
    {
        return
           from reading in context.Readings
           join product in context.Products
           on reading.ProductId equals product.SkuCode
           // where product.Brand is one or more brands from string[] brands
           // where product.Category is one or more categories from string[] categories
           where reading.Date == lastReadingDate
           select new LatestReading
           {
               ProductId = reading.ProductId,
               Distributor = reading.Distributor,
               Price = reading.Price
           };
    }
Turo
  • 1,537
  • 2
  • 21
  • 42

2 Answers2

2
private IEnumerable<LatestReading> getLatestReadings(string[] brands, string[] categories)
    {
        return
           from reading in context.Readings
           join product in context.Products
           on reading.ProductId equals product.SkuCode
           where (brands.Length == 0 || brands.Contains(product.Brand))
           where (categories.Length == 0 || categories.Contains(product.Category))
           where reading.Date == lastReadingDate
           select new LatestReading
           {
               ProductId = reading.ProductId,
               Distributor = reading.Distributor,
               Price = reading.Price
           };
    }
serhiyb
  • 4,753
  • 2
  • 15
  • 24
  • how about private IEnumerable getLatestReadings(IEnumerable brands, IEnumerable categories) for the second part of the question? – Bruce Dunwiddie Jan 26 '16 at 21:35
  • Still same idea just .Count() instead .Length – serhiyb Jan 26 '16 at 21:36
  • Ok, thank you checking this - I think this is totally what I needed. – Turo Jan 26 '16 at 21:36
  • thank you, I found this issue when executing this query http://stackoverflow.com/questions/8353948/the-linq-expression-node-type-arrayindex-is-not-supported-in-linq-to-entities . The other response works fine for me + I get some additional insight. – Turo Jan 27 '16 at 07:22
2

Of course the key is to use Contains. And as you see from the link, it works on IEnumerable<T>, so that should answer the second part of the question - you can pass any IEnumerable<string> including string[], List<string> etc.

While you can use the technique from another anwer, it would generate a strange SQL query (check it out). Anytime you need a dynamic filtering, a better approach would be to use the LINQ method syntax and dynamic Where chain, like this

// Products subquery with optional filters
var products = context.Products.AsQueryable();
if (brands.Any())
    products = products.Where(product => brands.Contains(product.Brand);
if (categories.Any())
    products = products.Where(product => categories.Contains(product.Category);
// Now the main query (just use products instead of context.Products)
return
    from reading in context.Readings
    join product in products
        on reading.ProductId equals product.SkuCode
    where reading.Date == lastReadingDate
    select new LatestReading
    {
        ProductId = reading.ProductId,
        Distributor = reading.Distributor,
        Price = reading.Price
    };
Community
  • 1
  • 1
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
  • Thank you Ivan. I find this more informative + I did find some issues with another response. – Turo Jan 27 '16 at 07:19