Using Linq and the Trim.Text for Search - c#

I am trying to convert this test code to C# and having a problem with the Trim command. Has anyone done anything similiar like this in C# going to use this with a text box for searching the aspx page.
Dim q = From b In db.Blogs _
Where b.BlogContents.Contains(txtSearch.Text.Trim()) Or _
b.BlogTitle.Contains(txtSearch.Text.Trim()) _
Select b

What is the issue you are having? And what LINQ provider is this? An in-memory set (LINQ-to-Objects)? Or LINQ-to-SQL? Or LINQ-to-Entities?
I suspect you are getting something about the db LINQ provider not knowing about Trim() - in which case, try doing the trim first:
string s = txtSearch.Text.Trim();
var q = from b in db.Blogs
where b.BlogContents.Contains(s) || b.BlogTitle.Contains(s)
select b;
This addresses two three separate issues:
1: captures: in the original, it is txtSearch that is captured into the query, which has complications; by evaluating the Trim first, it is s that is captured, which is a simple immutable string
2: expression complexity: with expression-based LINQ (i.e. to a database), the entire expression (including .Text, .Trim, etc) is part of the expression. If the LINQ provider doesn't recognise one or more of those, it will fail. By reducing it to a string first, all the LINQ provider needs to handle is a string, which every provider should be fine with.
(added)
3: repeated computation: LINQ-to-Objects is very literal; if you ask it to use a complex operation in a Where (etc), it will, even if it is obvious that the answer is unchanged per row; i.e. txtSearch.Text.Trim() shouldn't change per row, so why evaluate it per row? Evaluate it before the query and it is only done once.

not sure what you are asking but the Trim function in c# is the same.
http://msdn.microsoft.com/en-us/library/t97s7bs3.aspx

I've come across this too when switching to C#. The intellisense is way worse in C# : <
Make sure you aren't leaving out the () after Trim.

Related

C# 7 Out variable and pattern variable declarations are not allowed within a query clause

Why out variables are not allowed in query clause?
If I use out variables here it fails:
string json = "{'PayDays':['2017-07-07','2017-07-21','2017-08-04','2017-08-18']}";
var pd = JsonConvert.DeserializeObject<Accounting>(json);
var rm = from item in pd.PayDays
where (DateTime.TryParse(item, out DateTime dateresult)) ?
dateresult.Subtract(DateTime.Now).Days >= 0 ? true : false : false
select item;
rm.Dump();
But old way works:
DateTime result;
var rm = from item in pd.PayDays
where DateTime.TryParse(item, out result) ? (result.Subtract(DateTime.Now).Days >= 0 ? true : false) : false
select item;
rm.Dump();
Here are the relevant LDM notes.
The conclusion:
We won't have time to do this feature in C# 7.0. If we want to leave ourselves room to do it in the future, we need to make sure that we don't allow expression variables in query clauses to mean something else today, that would contradict such a future.
The current semantics is that expression variables in query clauses
are scoped to only the query clause. That means two subsequent query
clauses can use the same name in expression variables, for instance.
That is inconsistent with a future that allows those variables to
share a scope across query clause boundaries.
Thus, if we want to allow this in the future we have to put in some
restrictions in C# 7.0 to protect the design space. We have a couple
of options:
Disallow expression variables altogether in query clauses
Require that
all expression variables in a given query expression have different
names
The former is a big hammer, but the latter requires a lot of
work to get right - and seems at risk for not blocking off everything
well enough.
and
We will neither do expression variables nor deconstruction in C# 7.0, but would like to do them in the future. In order to protect our ability to do this, we will completely disallow expression variables inside query clauses, even though this is quite a big hammer.
The problem is that the translation you showed works fine for normal LINQ to objects, but would be problematic for other providers, like PLINQ or Entity Framework.
For example, consider the translation you proposed for your query modified to use PLINQ:
DateTime result;
var rm = from item in pd.PayDays.AsParallel()
where DateTime.TryParse(item, out result) ? (result.Subtract(DateTime.Now).Days >= 0 ? true : false) : false
select item;
var list = rm.ToList();
This code is not thread-safe, because multiple threads share a single result variable and you're likely going to get incorrect results, because they will try to use it at the same time.
There are ways to correctly translate such queries, at least in some cases, but they're not trivial, so out variables are simply not allowed in LINQ query syntax. Though there is a proposal to allow them in a future version of C#.

String.ToLowerInvariant not working in lambda expression [duplicate]

I'm using SQL Server 2005, with a case sensitive database..
In a search function, I need to create a Linq To Entities (L2E) query with a "where" clause that compare several strings with the data in the database with these rules :
The comparison is a "Contains" mode, not strict compare : easy as the string's Contains() method is allowed in L2E
The comparison must be case insensitive : I use ToLower() on both elements to perform an insensitive comparison.
All of this performs really well but I ran into the following Exception :
"Argument data type ntext is invalid for argument 1 of lower function" on one of my fields.
It seems that the field is a NText field and I can't perform a ToLower() on that.
What could I do to be able to perform a case insensitive Contains() on that NText field ?
Never use .ToLower() to perform a case-insensitive comparison. Here's why:
It's possibly wrong (your client collation could be, say, Turkish, and your DB collation not).
It's highly inefficient; the SQL Emitted is LOWER instead of = with a case-insensitive collation.
Instead, use StringComparison.OrdinalIgnoreCase or StringComparison.CurrentCultureIgnoreCase:
var q = from f in Context.Foos
where f.Bar.Equals("hi", StringComparison.OrdinalIgnoreCase)
select f;
But for Contains() there's a problem: Unlike Equals, StartsWith, etc., it doesn't have an overload for a StringComparison argument. Why? Good question; ask Microsoft.
That, combined with SQL Server's limitation on LOWER means there's no simple way to do what you want.
Possible workarounds might include:
Use a full text index, and do the search in a procedure.
Use Equals or StartsWith instead, if possible for your task
Change the default collation of the column?
Use a lambda expression here and create an intermediary list that can handle the lower clause.
var q = Context.Foos.ToList().Where(s => s.Bar.ToLower().Contains("hi"));
Not terribly efficient, but it does work. If you have additional predicates in your where clause then it works to your advantage:
var q = Context.Foos.Where(p => p.f1 == "foo" && p.f2 == "bar").
ToList().Where(s => s.Bar.ToLower().Contains("hi"));
as we known , this is a very "bugged" situation.
and it bugs me a lot.
Today, i decide to create a view as:
select * from tableName
where theColumn like '%key%'
then load this view into EF.
life is getting easy!

How to write Nested LINQ for specific scenario

Apologized to post a problem for which i could not construct anything solid. it is very shameful for me to post like this kind of question even after having so high reputation for this web site.
Most of the time i write sql in store procedure in sql server and hardly use LINQ. so facing problem to construct a nested LINQ query for a specific scenario. just wonder if anyone could help me or give me hints to construct such query with linq.
here i am providing a sample sql query which i want to construct the same one with LINQ.
SELECT EmployeeName,
(Select count(*) from table1 where condition) as data1,
(Select count(*) from table1 where condition) as data2,
(Select count(*) from table1 where condition) as data3
though i have seen couple of nested linq sample from these urls but still could not figure out how to construct mine.
http://odetocode.com/blogs/scott/archive/2007/09/24/nested-selects-in-linq-to-sql.aspx
https://social.msdn.microsoft.com/Forums/en-US/00340c95-221a-4b16-9c47-d1acbf2415dc/linq-nested-select-issue?forum=linqtosql
http://www.mercurynewmedia.com/blog/blog-detail/mercury-new-media-blog/2014/05/19/linq-join-queries-vs-nested-sub-queries
http://www.codethinked.com/the-linq-selectmany-operator
Nested Select linq query
http://www.java2s.com/Code/CSharp/LINQ/Nestedquerylist.htm
so just wonder if anyone could help.
This is a good example of something to do in Linq. You will find that you can do this easily and even more powerful queries if you understand two things:
Don't try to overly literally translate from SQL into Linq.
Lambdas.
The first is easy to understand but hard to carry out. Some of the Linq keywords are intentionally like SQL keywords. Linq tries to mirror some aspects of SQL without working in exactly the same way. One key difference is that with Linq, each function yields (no pun intended) a Linq object which can be passed to another Linq function. Thus filtering, transforming, aggregating, etc. can be done repeatedly in the order the programmer chooses. In SQL a single query is built up of several elements such as WHERE, FROM, some of which are optional, and the SQL engine decides in which order to evaluate them.
Get LinqPad and use it for playing with queries, and for doing database queries instead of writing SQL code in SSMS. When you have seen and written enough Linq constructs, you will no longer be writing transliterated SQL, and you will be able to switch back and forth between the two.
Secondly, make sure you understand lambdas. What does
x => x + 23
mean? What is its type? What is the type of its argument and return value? What about
(x, y) => x + y * 23
and
() => "Fish"
?
Select in Linq takes as argument a function. What Select does is the simplest possible thing to understand - it takes an iterator of input objects and a function, and returns an iterator of output objects, which are the input objects having had the function applied to them. This is actually easier to understand with a lambda than with a named function.
Remember that everything in C# has a type. A lambda has a type, even if the type is not explicit. Error messages usually tell you exactly what is wrong, except that sometimes they can be misinterpreted and seem to be pointing to exactly the wrong piece of code, and this can be very time-consuming to figure out. Break down the code you are writing into as small pieces as possible, and debug them in Linqpad.
You can get a long way with this. Try looking at a suggestion for a similar query to yours below and see if you can build on it.
/* A very simple dataset */
string s = "THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG";
var x = s.Split();
/* The letters list plays the role of your EmployeeName */
var letters = new List<String>{"A", "E", "I", "O", "U"};
var result = letters
.Select(letter => new {letter = letter,
startswith = x.Count(w => w.StartsWith(letter)),
contains = x.Count(w => w.Contains(letter)),
endswith = x.Count(w => w.EndsWith(letter))});
If you get this far, you might want to learn more about how the Linq functions operate on iterators. Check out Jon Skeet's Edulinq series of blog posts: http://codeblog.jonskeet.uk/2011/02/23/reimplementing-linq-to-objects-part-45-conclusion-and-list-of-posts/ He reimplements Linq to show how it might be designed and how it should work.
Linqpad and Edulinq and two of the best programming resources I know of, in any language, and I recommend them in almost every Linq question I answer. Check them out.

Case-insensitive "contains" in Linq

I have a mvc project which I use linq in it.
In my database there is some records, for example "Someth ing","SOmeTH ing","someTh ing","SOMETH ING","someTH ING"
I want to do this:
SELECT * FROM dbo.doc_dt_records WHERE name LIKE '%' + #records.Name + '%'
However if I run this code, list.Count returns 0. What should I do?
records.Name = "someth ing"; //for example
var rec = db.Records.ToList();
var lists = rec.Where(p => p.Name.Contains(records.Name)).ToList();
if (lists.Count > 0)
{
// do sthng
}
Thanks for your helps...
the easy way is to use ToLower() method
var lists = rec.Where(p => p.Name.ToLower().Contains(records.Name.ToLower())).ToList();
a better solution (based on this post: Case insensitive 'Contains(string)')
var lists = rec.Where(p =>
CultureInfo.CurrentCulture.CompareInfo.IndexOf
(p.Name, records.Name, CompareOptions.IgnoreCase) >= 0).ToList();
That is totally not a LINQ issue.
Case sensitiivty on the generated SQL depends on the collation relevant for the table. Which in your case likely is case insensitive.
You would get the same result from any SQL you emit.
use IndexOf and StringComparison.OrdinalIgnoreCase:
p.Name.IndexOf(records.Name, StringComparison.OrdinalIgnoreCase) >= 0;
You can create an extension function like this:
public static bool Contains(this string src, string toCheck, StringComparison comp)
{
return src.IndexOf(toCheck, comp) >= 0;
}
To my understanding, this question does not have an unambiguous answer. The matter is that the best way of doing this depends on details which aren't provided in the question. For instance, what exact ORM do you use and what precise DB server you are connected to. For example, if you use Entity Framework against MS SQL Server, you better do not touch your LINQ expression at all. All you need to do is to set the case-insensitive collation on the database/table/column you compare your string with. That will do the trick much better than any change of your LINQ expression. The matter is that when LINQ is translated to SQL, it better be the straight comparison of the column having case-insensitive collation to your string than anything else. Just because it usually works quicker and it is the natural way to do the trick.
You do not want the final query to be something like:
SELECT *
FROM AspNetUsers U
WHERE UPPER(U.Name) LIKE '%SOMETHING%';
It is much better to come up with something like:
SELECT *
FROM AspNetUsers U
WHERE U.Name LIKE '%SOMETHING%';
But with a case-insensitive collation of [Name] column. The difference is that if you have let's say index containing [Name] column, the second query might use it, the first one would do the full scan of the table anyway.
So if let's say records references to DBSet<T> and the record is just one object of type T. You code would be like this:
var lists = records.Where(p => p.Name.Contains(record.Name)).ToList();
And you do the rest on SQL-server. Or if all you need to know is there any value in the list and do not need these values, it would be even better to do like this:
if (records.Any(p => p.Name.Contains(record.Name)))
{
// do something
}
Generally speaking, if you use any sort of ORM connected to any sort of SQL server, you better do case-insensitivity by setting up appropriate parameters of your server/database/table/column. And only if it is impossible or by far too expensive, you consider other possibilities. Otherwise, you might bang into some unexpected and very unpleasant behaviour. For instance, Entity Framework Core 2.x if it cannot translate your LINQ expression straightway into SQL query, is doing different tricks replacing server-side operations with client-side ones. So you can end up with a solution which fetches all data from the table to the client and filter it there. It might be quite a problem if your table is big enough.
As for the situation when LINQ query is processed locally, there are a lot of ways to do the trick. My favourite one is the next:
var lists = records.Where(p => p.Name
.Contains(record.Name, StringComparison.InvariantCultureIgnoreCase))
.ToList();
try this
var lists = rec.Where(p => String.Equals(p.Name,records.Name,StringComparison.OrdinalIgnoreCase)).ToList();
refer here for documentation

Passing query data from LINQ to method in same query

I was able to create a LINQ statement that I thought was strange and wanted to see if anyone else had experience with it.
I've simplified it to this:
var x = db.Test
.Where(a => a.Field1 == Utils.CreateHash(Preferences.getValue(a.Field2)))
.FirstOrDefault();
Now how does this translate to database code? Wouldn't LINQ need to do a double query for every single row, i.e. for row a:
1) Query a.Field2
2) Return value to run Utils.CreateHash(Preferences.getValue(a.Field2))
3) Take that value from step 2 and compare it against a.Field1
4) Repeat 1-3 until I've gone through all the rows or returned a matching row
Wouldn't this be extremely inefficient? Or is LINQ smart enough to run this in a better way? Note, I haven't actually run this code so another possibility is a runtime error. Why wouldn't LINQ be smart enough to detect a conflict then and not let me compile it?
The query as is will not work since have a call to Utils.CreateHash in your lambda that you are trying to execute on the DB - in that context you cannot execute that method since there simply is no equivalent on the DB side hence the query will fail.
In general the ability of 3rd party Linq IQuerable providers (e.g. Linq to SQL, Linq to Entities) to access in memory constructs such as methods or classes is very limited, as a rule of thumb at most accessing primitive values or collections of primitives will work.
Just to add fast...
A good example to know how this works would be to write (extreme case I agree, but best :) or go through the source code for a custom (open source) LINQ provider (e.g. http://relinq.codeplex.com/ has one etc.).
Basically (I'm simplifying things here a bit), a LINQ provider can only 'map' to Db (supported SQL, functions) what he 'knows' about.
i.e. it has a standard set it can work with, other than that, and with your custom methods (that do not translate to constants etc.) in the frame, there is no way to resolve that on the 'Db/SQL side'.
E.g. with your 'custom' linq provider (not the case here) you could add a specific extension call e.g. .MyCalc() - which would be properly resolved and translated into SQL equivalent - and then you'd be able to use it.
Other than that, I think if I recall correct, provider will leave that as an expression, to resolve when it returns from the Db 'fetch', query operation. Or complain about it in certain cases.
Linq is based on IQueryable - and you can take a look at extension methods provided there for SQL equivalents supported.
hope this helps
EDIT: whether things 'work' or not doesn't matter - it still doesn't mean it'd execute on the Db context - i.e. it'd be unacceptable performance wise in most cases. IQueryable works with expressions (and if you look at the interface) - and linq is executed when you invoke or enumerate usually. At that point some of the expressions may evaluate to a const value that can be worked into a SQL, but not in your case.
Best way to test is to test back the SQL generated by query (possibly this one I think Translate LINQ to sql statement).
No.
The LINQ provider will run a single SELECT query that selects both fields, then execute your lambda expression with the two values for each returned row.

Categories