Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: Is it possible to do case-insensitive search #128

Closed
rajeshmuraleedharan opened this issue Dec 12, 2017 · 19 comments
Closed

Question: Is it possible to do case-insensitive search #128

rajeshmuraleedharan opened this issue Dec 12, 2017 · 19 comments
Assignees
Labels

Comments

@rajeshmuraleedharan
Copy link

I would like to do case-insensitive search with startswith,endwith and Contains. Please let me know this is possible or not.

@rajeshmuraleedharan rajeshmuraleedharan changed the title Is it possible to case-insensitive search Is it possible to do case-insensitive search Dec 12, 2017
@StefH
Copy link
Collaborator

StefH commented Dec 20, 2017

This is related to your SQL-server settings ?

@StefH StefH added the question label Dec 20, 2017
@StefH StefH changed the title Is it possible to do case-insensitive search Question: Is it possible to do case-insensitive search Jan 6, 2018
@mhosman
Copy link

mhosman commented Jan 15, 2018

@rajeshmuraleedharan When you install SQL Server you must specify the collation. CI is for case insensitive and AI is for accent insensitive. Anyway, It could be great to make requests in CI, AI, CS or AS "on demand".

@jogibear9988
Copy link
Contributor

jogibear9988 commented Apr 19, 2018

I think, you should able to use: title.Contains("string", StringComparison.OrdinalIgnoreCase); if it works is a question of your linq adapter

@StefH
Copy link
Collaborator

StefH commented Jul 24, 2018

@jogibear9988 This will not work for this library I think.

@ghost
Copy link

ghost commented Nov 6, 2018

Sadly it doesn't work, the part "StringComparison" is treated as a property and you get an error saying, that the property or field 'StringComparison' exists in the currently used type.
However, you can use the string value of the enum, described in the Enum Type Support Section.

users.Where("GivenName.Contains(\"sa\", \"OrdinalIgnoreCase\")");

Works perfectly for me :-)

@wilari932
Copy link

wilari932 commented Jan 30, 2019

How do you do a case sensitive search with this library ???

Query.Where($"{dataPropertie.Name}.ToString().Trim().ToLower().Contains(@0)", cols.Values.ToStringNullSafe().Trim().ToLower()).OrderBy(dataPropertie.Name).ToList();

I tried something like this but is not working

@zspitz
Copy link

zspitz commented Nov 15, 2020

@rajeshmuraleedharan With #450, StringComparison is now supported, so the following should work:

users.Where("GivenName.Contains(\"sa\", StringComparison.OrdinalIgnoreCase)");

@wilari932 How would you write a case-insensitive search using standard expression trees? If this would work:

var cols1 = cols.Values?.ToString().Trim();
Query = Query.Where(x => x.Contains(cols1, StringComparison.OrdinalIgnoreCase));

then the following should also work:

var cols1 = cols.Values?.ToString().Trim();
Query = Query.Where("Contains(@0, StringComparison.OrdinalIgnoreCase)", cols1);

@khmurach
Copy link

khmurach commented Dec 6, 2020

users.Where("GivenName.Contains("sa", StringComparison.OrdinalIgnoreCase)");

Still does not work for me in 1.2.6:
No applicable method 'Contains' exists in type 'String'

@zspitz
Copy link

zspitz commented Dec 6, 2020

@khmurach How are you escaping the quotation marks? Also, is this being run against a database or other Queryable provider?

@khmurach
Copy link

khmurach commented Dec 6, 2020

@khmurach How are you escaping the quotation marks? Also, is this being run against a database or other Queryable provider?

Yes, I'm escaping. I'm using Where on List().AsQueryable()

@zspitz
Copy link

zspitz commented Dec 6, 2020

@khmurach This works for me:

var lst = new List<User>();
var qry = lst.AsQueryable().Where("GivenName.Contains(\"sa\", StringComparison.OrdinalIgnoreCase)");

public class User {
    public string? GivenName { get; set; }
}

Visualizing qry.Expression:
image
Which framework are you targeting?

@khmurach
Copy link

khmurach commented Dec 6, 2020

@zspitz I have generic method so there is no properties to use in standard Where(x=>x.Name.Contains("value")).

IQueryable<T> ApplyFilter(IQueryable<T> dataAll, object filter)

This line works fine:
dataQueryable = dataQueryable.Where("{0}.ToLower().Contains(@0)".FormatWith(item.Key), item.Value.ToString().ToLower());
But I would like to get rid of ToLower()

@khmurach
Copy link

khmurach commented Dec 6, 2020

@khmurach This works for me:

var lst = new List<User>();
var qry = lst.AsQueryable().Where("GivenName.Contains(\"sa\", StringComparison.OrdinalIgnoreCase)");

public class User {
    public string? GivenName { get; set; }
}

Visualizing qry.Expression:
image
Which framework are you targeting?

targetFramework="net451"

@zspitz
Copy link

zspitz commented Dec 6, 2020

@khmurach It seems that .NET Framework 4.5.1 doesn't support this overload of Contains:
image
How would you do this with a strongly-typed query?

N.B. The filter you are passing into ApplyFilter could also be generic:

IQueryable<T> ApplyFilter(IQueryable<T> dataAll, Func<T, bool> filter) {

}

and then you would have strong-typing on the filter itself. Although I don't quite see what it gives you over the standard .Where.

@khmurach
Copy link

khmurach commented Dec 6, 2020

Even in this simplified example, first two queries works fine but the last one throws error:

var items = new List<ListItem>() { new ListItem { Title = "John" }, new ListItem { Title = "Adam" }, new ListItem { Title = "john" } };
// works fine
var result1 = items.AsQueryable().Where("Title.ToLower().Contains(\"jo\")").ToList();
// works fine
var result2 = items.AsQueryable().Where(x => x.Title.Contains("jo", StringComparison.OrdinalIgnoreCase)).ToList();
// throws exception
var result3 = items.AsQueryable().Where("Title.Contains(\"jo\", StringComparison.OrdinalIgnoreCase)").ToList();

@khmurach
Copy link

khmurach commented Dec 6, 2020

I'm using
object filter
in
IQueryable<T> ApplyFilter(IQueryable<T> dataAll, object filter)
to be able to use any object (projection) as a filter and to use reflection to scan props and values and apply them as a filter to List:

var usersCache = _repository.GetAll<User>();
var filter1 = new User{ FirstName = "jo", LastName = "wes" };
var filter2 = new UserQuery{ FirstName = "jo" };
var result1 = ApplyFilter(usersCache, filter1);
var result2 = ApplyFilter(usersCache, filter2);

@ButtiBBQ
Copy link

ButtiBBQ commented Aug 3, 2021

Any updates on how to do an case invariant search?

@Beamer92
Copy link

Beamer92 commented Apr 12, 2022

I'm also having this problem with Contains with the System.Linq.Dynamic.Core package at version 1.2.18, but only when running my actual code. If I run Unit tests everything works perfectly.

[Fact]
    public void DynamicLinq_SingleContains_SimpleText_CaseInsensitiveOverload()
    {
      var filter = "(Name != null && Name.Contains(\"Blu\", StringComparison.CurrentCultureIgnoreCase))";
      var data = GetDynamicLinqTestData().AsQueryable();

      var filteredData = data.Where(filter).ToArray();
      Assert.Single(filteredData);
    }

    [Fact]
    public void DynamicLinq_SingleContains_ReplacementText_CaseInsensitiveOverload()
    {
      var filter = "(Name != null && Name.Contains(@0, StringComparison.CurrentCultureIgnoreCase))";
      var filterParams = new List<object>();
      filterParams.Add("Blu");
      var data = GetDynamicLinqTestData().AsQueryable();

      var filteredData = data.Where(filter, filterParams.ToArray()).ToArray();
      Assert.Single(filteredData);
    }

Both of these tests work fine in XUnit. But when I run my code that creates the exact same thing (either way, and I have unit tests on those create functions too) I get System.Linq.Dynamic.Core.Exceptions.ParseException No applicable method 'Contains' exists in type 'String'

I've tried also using the older method of doing just an escaped string of the enum like "CurrentCultureIgnoreCase" but that doesn't work either. Doesn't matter which enum I use, OrdinalIgnoreCase doesn't work either. It does appear to work if I let it be case sensitive, but that's not ideal.

I just don't understand why it works in unit tests and not in practice.

I will also note that string.StartsWith and EndsWith both DO work in unit tests and in practice using the case sensitive enums. Which is even weirder.

Update:

  • Nevermind, I forgot the Unit Test Project is using .Net 5.0 and the actual project is using Framework 4.8 where that String.Contains overload doesn't exist apparently. Yay old code making things hard.

@StefH StefH self-assigned this Dec 5, 2023
@StefH
Copy link
Collaborator

StefH commented Dec 5, 2023

Closing..

@StefH StefH closed this as completed Dec 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

9 participants