Search code examples
c#arrayslinqiqueryableef-core-2.2

How to search with LINQ entites having string[] array properties and find these containing any of string from string[] array?


With EF Core 2.2 I am having entities with string[] array properties, where in ApplicationDbContext they are retreived with:

modelBuilder.Entity<FruitBasket>()
            .Property(e => e.FruitTypes)
            .HasConversion(
                v => string.Join(',', v),
                v => v.Split(',', StringSplitOptions.RemoveEmptyEntries));

For example an entity mat contain in FruitType column an strning array: {"Apple", "Banana", "Orange"} saved in the database as: Apple,Banana,Orange

I am trying to find in my DB all objects containing any of string from my input string, lets say any of:

string[] BasketSearchedFruitTypes = new string[] { "Apple", "Grapefruit", "Pineaple" }

My IQueryable:

IQueryable<BasketModel> baskets = GetBasketsQueryable(); //BasketModel contains FruitType string[] prop

To search for entities I have right now LINQ that says:

if (search.BasketSearchedFruitTypes != null && search.BasketSearchedFruitTypes.Length != 0)
baskets = baskets
   .Where(data => search.BasketSearchedFruitTypes
   .Any(x => data.FruitType
   .Contains(x)));

Unfortunatelly it returns me nothing and I ran out of ideas.

EDIT 1: after using expression:

baskets = baskets
   .Where(data => search.BasketSearchedFruitTypes
   .Any(x => data.FruitType
   .Contains(x)));

when I try take it to the List<>, I am getting ArgumentNullException. Also I am not able to use foreach, .Count() on it. Same I have with:

var result = baskets.Where(data => search.BasketSearchedFruitTypes.Intersect(data.FruitType).Any();

EDIT 2: I just noted, that foreach loop goes through returned IQueryable, but at some point breaks giving ArgumentNullException. Even try catch inside of the loop does not help...

EDIT 3: Actually when I place foreach of returned IQueryable into try catch, it is kind of temporary solution and it works fine. But still I do not understand why it crashes on enumerating (looping, not code inside of the loop).


Solution

  • If I make a list similar at your DB protocol Than this codes work for me.

    using System.Collections.Generic;
    using System.Linq;
    
    namespace ConsoleApp2
    {
        class BuilderClass
        {
            List<BasketModel> baskets;
    
            public BuilderClass()
            {
                baskets = new List<BasketModel>() 
                { new BasketModel { FruitType = new string[] { "Apple", "Grapefruit", "Pineaple", "Bing Cherry", "Cantaloupe" } },
                  new BasketModel { FruitType = new string[] { "Grapefruit", "Cantaloupe", "Pineaple", "Boysenberries", "Apple" } },
                  new BasketModel { FruitType = new string[] { "Clementine", "Bing Cherry", "Boysenberries", "Cantaloupe", "Entawak" } },
                  new BasketModel { FruitType = new string[] { "Entawak", "Grapefruit", "Apple", "Pineaple", "Cantaloupe" } },
                  new BasketModel { FruitType = new string[] { "Apple", "Pineaple", "Bing Cherry", "Entawak", "Grapefruit" } }
                };
            }
    
            string[] BasketSearchedFruitTypes = new string[]
            { "Apple", "Grapefruit", "Pineaple" };
    
            public void check()
            {
                var qbaskets = baskets.AsQueryable();
                if (BasketSearchedFruitTypes != null && BasketSearchedFruitTypes.Length != 0)
                {
                    var result = qbaskets.Where(data => BasketSearchedFruitTypes.Any(x => data.FruitType.Contains(x))).ToList();
                    // result have list with count of 4
                }
            }
        }
    
        class BasketModel
        {
            public string[] FruitType { get; set; }
        }
    }