daustinash
daustinash

Reputation: 484

LINQ - Refactor .Contains comparison on IEnumerable<string> to be case sensitive

I have what seems like it should be a fairly simple linq issue. I'm doing a string comparison using Contains that is behaving case sensitively and I need it to be case insensitive. I understand that the proper way to do this is by using the IndexOf method overload that takes a StringComparison.OrdinalIgnoreCase argument.

The problem is that the object I'm hanging the IndexOf off of (emailAddresses) is an enumeration of strings so there is no IndexOf available. I also tried emailAddresses.Contains(x.Email, StringComparer.InvariantCultureIgnoreCase but it throws this error:

LINQ to Entities does not recognize the method 'Boolean Contains[String](System.Collections.Generic.IEnumerable 1[System.String], System.String, System.Collections.Generic.IEqualityComparer 1[System.String])' method

How do I refactor this so that the .Where(x => emailAddresses.Contains(x.Email) portion is case insensitive?

public IList<string> FindInvalidEmails(UserContext userContext, IEnumerable<string> emailAddresses)
{
    var validEmails = new List<string>();

    emailAddresses.ForEachChunk(100, emailAddressesChunk =>
        validEmails.AddRange(_enterpriseRepositoryFactory.GetMemberRepository(userContext.EnterpriseId).FindAll()
                                    .Where(x => emailAddresses.Contains(x.Email) && !x.IsDeleted)
                                    .Select(x => x.Email)
                                    .ToList())
    );

    return emailAddresses.Except(validEmails).ToList();
}

Upvotes: 3

Views: 2023

Answers (2)

MarcinJuraszek
MarcinJuraszek

Reputation: 125660

How about:

.Where(x => emailAddresses.Select(y => y.ToLower()).Contains(x.Email.ToLower()) 

It will change all your collection elements into lowercase versions and try to find lowercased version of user email within that collection.

You could pick ToUpper instead, it should make no difference.

If it was a LINQ to object query, you'd probably should use ToLowerInvariant, but because it's not supported by LINQ to Entities, you have to use ToLower here`

Upvotes: 9

NinjaNye
NinjaNye

Reputation: 7126

If emailAddresses is IEnumerable you could do....

.Where(x => emailAddresses.Any(em => em.ToLower() == x.Email.ToLower()) 

or

//Build a list of lower emails in memory
var lowerEmails = emailAddress.Select(em => em.ToLower()).ToList();
...
.Where(x => lowerEmails.Contains(x.Email.ToLower()) 

Upvotes: 2

Related Questions