1

I'm trying to do a text search on a partial property match on related entities.

My entities are:

public class TradeContact
{
    [Key]
    public int TradeContactId { get; set; }

    public virtual ICollection<Region> Regions { get; set; }

}

public class Region
{
    [Key]
    public int RegionId { get; set; }
    public virtual ICollection<TradeContact> TradeContacts { get; set; }
}

My goal is that if a TradeContact has the following regions: Sydney, Brisbane, Darwin, then I should be able to search for 'Syd' to retrieve that TradeContact record.

Currently I'm searching like this:

TradeContacts = TradeContacts
    .Where(s => s.Regions.Select(x => x.Name.ToUpper())
    .Contains(searchString.ToUpper()));

This code finds full matches, so 'Sydney' will return my TradeContact, but it doesn't work on partial matches.

What have I done wrong?

Robbie Mills
  • 2,705
  • 7
  • 52
  • 87
  • 1
    @wudzik This is not a duplicate of that question. OP already knows how to perform a comparison, they are asking how to perform the comparison on a list of strings using LINQ. More precisely, they are asking what is wrong with the current solution they have in that it isn't matching on partial matches. – Abion47 Nov 15 '16 at 07:02
  • 1
    Well until this question gets unflagged, here is your working code, and apologies that I can't format it better as a comment: `TradeContacts = TradeContacts.Where(s => s.Regions.Any(r => r.Name.ToUpper().Contains(searchString.ToUpper())));` – Abion47 Nov 15 '16 at 07:11
  • @wudzik this question is not related to the question you marked as duplicate in _any_ way at all. – Evk Nov 15 '16 at 07:23
  • @Evk sorry, my bad – Kamil Budziewski Nov 15 '16 at 07:34

3 Answers3

2

You can try something like this

var result = TradeContacts.Where(s => s.Regions.
             Any(x => x.Name.ToUpper().Contains(searchString.ToUpper()));

if(result!=null)
//do your stuff.
mybirthname
  • 17,949
  • 3
  • 31
  • 55
2

It's important to understand why current approach does not work.

TradeContacts
.Where(s => s.Regions.Select(x => x.Name.ToUpper())
.Contains(searchString.ToUpper()));

If translate that to human language, it would be: give me Contacts where the list of Regions contains region with the Name equal to searchString. So Contains you use is not String.Contains, it's IEnumerable.Contains:

var regionNames = new List<string>();
var match = regionNames.Contains(searchString);

As you see, that indeed matches only when region name equals your search string.

TradeContacts.Where(s => s.Regions.
   Any(x => x.Name.ToUpper().Contains(searchString.ToUpper()));

This one is different: give me all Contacts where any region has Name which contains searchString.

Evk
  • 98,527
  • 8
  • 141
  • 191
1

Okay, here's the answer that I posted before:

TradeContacts = TradeContacts.Where(
            s => s.Regions.Any(
                r => r.Name.ToUpper().Contains(searchString.ToUpper())));

The reason your current code isn't working is because you are performing the Contains check on your list of names, which checks the list for exact matches, when what you want to be doing is checking the names themselves.

Abion47
  • 22,211
  • 4
  • 65
  • 88