How to make LINQ case sensitive and NOT case sensitive depending on the situation?
I'm using sql server 2008 and Entity Framework 4.0.
I changed the COLLATION to make SQL Server case sensitive. so that for scenarios like these:
query = query.Where(x => x.Username == username);
it works great.
However I need to be able to pull out data from db ignoring case when searching by subject (or name or similar) like so:
query = query.Where(x => (x.Name.Contains(Name)));
which doesn't work when record is "TestString" and i'm looking for "test" or "Test" or similar. How would i make it so that when it would find a text or part of a string in a text?
thanks
LINQ has no concept of case sensitivity, it only cares about boolean evaluation. So if you want to ignore case, you should do something like:
query = query.Where(x => (x.Name.ToLower().Contains(Name.ToLower())));
Chances are you will want to pass a CultureInfo to ToLower() (or use ToLowerInvariant()), and you might want to cache the result of Name.ToLower() so as to not have to perform that operation a potentially large number of times, but this should get you started.
query = query.Where(x => string.Equals(x.Name, Name, StringComparison.CurrentCultureIgnoreCase));
Read my reply to this:
String.Equals() not working as intended
It isn't the reply you wanted, probably :-)
Ah... and if you have to convert to the same case to make comparisons, ToUpper is better than ToLower. Don't ask me why. But you can read here: Case insensitive string compare in LINQ-to-SQL
Queryable.Contains has an overload taking an IEqualityComparer<T> used for comparision. See msdn. If you supply a case insensitive comparer, this should work - I'm quite sure there is one in the framework already.
Related
There are many posts online and on stack overflow talking about solving the issue of case insensitive likes. I guess this is due to these peoples database being by default case sensitive.
Sql server by default uses a case insensitive collation, so i would never have that problem by default.
But unfortunately, I have the opposite problem. I need to do a one off case sensitive equals or like.
I cannot set the collation of the table, so would ideally run some sql like this
WHERE Column COLLATE Latin1_General_CS_AS = 'CaseSensitive'
As far as i can see, i dont understand why an InsensitiveLike has been implmeneted as surely we could have just done something like this
.Where(x=> x.Column.ToLower() == variable.ToLower())
But my issue is not able to be worked around in any other way that doing the above collaction change.
It would be nice if this was built in rather than having to write sql queries.
Have i missed something or is there really no way to do this?
I ask because a thorough Google search returns no clue as to how to do this.
I am trying to pull an example of a column field which is rarely used and is unfortunately littered with newlines and dashes even in empty ones, so I can't just ask for ones that have data. I need to ask for a column that has at least 10-15 characters or something like this. I can also imagine this query being useful for validating pre-existing data. I know about the validator that does this, but I'm not trying to validate, I'm trying to search.
Thanks!
Seems ActiveRecord does not support this. But you can do it anyway like (Mysql example)
Model.where("CHAR_LENGTH(text_field) = ?", 10)
in Postgres the same should work but in documentation it says to use char_length()
Also what you could do is on saving the record store the size of the field with a callback
before_save {|r| r.text_field_size = r.text_field.size}
With this you can now query with that, wich will be DB agnostic.
Model.where(text_field_size: 10)
I think you'll have to write so part of the request in SQL.
For MySQL, use something like :
Model.where("CHAR_LENGTH(field_name) >= ?", min_length)
I just can't seem to wrap my mind around this concept... I want to allow users to apply a number of "filters" to a dataset (preferably in the querystring to allow bookmarking the filtered results), retrieved using Rob Conery's Massive dynamic data access "tool".
I could simply write a whole bunch of if's, then write a direct query by each "rule" I catch... but that seems to defeat the purpose of "dynamic sql".
Is there a general pattern/best practice for this in C#/ASP.NET MVC?
I think the concept is a bit broad to say there's a pattern/best practice for doing something like this. That said, I think using something like LINQ to SQL or Entity Framework would make a good dynamic query engine because you can do stuff like this:
var query = DBContext.Items.Select(x => x.Name);
switch(QueryString["Type"])
{
case "Dog":
query = query.Where(x => x.Type == "Dog";
break;
case "Cat":
query = query.Where(x => x.Type == "Cat";
etc....
}
query = query.Where(x => x.Owner.Name == QueryString["Owner"]);
ResultsDataGrid.Datasource = query;
Obviously some psuedo-code there, but the good thing about LINQ to SQL in this case is the deferred execution. query doesn't get run until the databinding, and includes whatever filters you add dynamically. It also gives you type-safety and will prevent SQL Injection. You can do something similar by actually building up the SQL query that will be run at the end, but it's going to be error-prone and require a lot of checks and balances.
I'm making a search with NHibernate 3.0 IQueryOver, where I have a keyword for a search. I need to search in a string to see if it is part of the string,
Query().Where(e => e.Name.Contains(keyword)).List();
But this does not do the job as expected. How should such a search be performed?
I checked the NHibernate source and the ExpressionProcessor for the QueryOver string like you posted above does not support Contains. The operations it supports are IsLike and IsIn. You could either use IsLike or if you are keen on Contains, use Linq. For example :
(from user in db.Users
where names.Contains(user.Name)
select user);
or
query.Where(person.Name.IsLike("%test%")) //In QueryOver
I am guessing that you got an "Unrecognised method call" exception.
As far as I know (at least, for SQL Server, it doesn't seem to work with SQL Server Compact), NHibernate translates that IQueryable into a case insensitive "like '%keywork%'" where clause. Did you expect a case sensitive search?
In my application the user can defines search-conditions. He can choose a column, set an operator (equals, like, greater than, less or equal than, etc.) and give in the value. After the user clicks on a button and the application should do a search on the database with the condition. I use NHibernate and ask me now, what is the efficientest way to do this with NHibernate.
Should I create a query with it like (Column=Name, Operator=Like, Value=%John%)
var a = session.CreateCriteria<Customer>();
a.Add(Restrictions.Like("Name", "%John%"));
return a.List<Customer>();
Or should I do this with HQL:
var q = session.CreateQuery("from Customer where " + where);
return q.List<Customer >();
Or is there a more bether solution?
Thanks for your help.
Best Regards, Thomas
You can use either one of them. There might be hardly an differences between the two. But whatever you do make sure that your column names are in constants or are mapped to the column name otherwise your repository will be tightly coupled to your model definition i.e if you update the columnname you will have to go and update these statements yourself.
And when you are building the where clause makes ure you have a function that appends the right query. you will probably be having a switch case statement for the same.
In term of efficence there is no difference. In the HQL version I would prefer use a parameter instead of adding the where part as a string.
If you are using NH3.0 you can consider using QueryOver too, to avoid using string to describe your properties