C# LINQ search by position - c#

I'm trying to recreate the following SQL query in LINQ:
select * from table where column like 'RECORD_%01'
What I have is:
var data = from t in context.table
where t.column.StartsWith("RECORD")
&& t.column.EndsWith("01")
select t;
which is equivalent to:
select * from table where column like 'RECORD%01'
Can someone help me as to how I can add the condition for '_%', not '%'?
If you guys don't know what I'm talking about with the SQL issue, please check the following image, which explains SQL.

This is what you want (or something very similar):
https://learn.microsoft.com/en-us/dotnet/api/system.data.linq.sqlclient.sqlmethods.like
LINQ2SQL LIKE Command for Phrase
This allows you to specify a LIKE statement.
var data = from t in context.table
where SqlMethods.Like(t.column, "RECORD_%01")
select t;

From this it seems like you wanted to make sure that
It starts with RECORD
It ends with 01
And there is atleast one character after RECORD before 01
In this case you can check start with, end with and also the length.
var data = from t in context.table
where t.column.StartsWith("RECORD")
&& t.column.EndsWith("01")
&& t.column.Length>=9
select t;

Here's one way:
var data = from t in context.table
where t.column.StartsWith("RECORD")
&& t.column.EndsWith("01")
&& t.column.Length > 8
select t;
This makes sure that at there is at least one character between RECORD and 01.
Of course, depending on what Query Provider you're using, you may want to simply try use the LIKE operator using SqlMethods.Like, SqlFunctions.PatIndex or one of the methods describe here.

Related

How do I do an inner select in linq?

I have a database table called Customers. I run the following sql to get information about the first and second customer:
select FirstCustomerName, SecondCustomerName,
* from Customers where FirstCustomerName = SecondCustomerName
When I run this in sql it gives me what I want, so that one is ok. The problem is when I want to do the same thing in Linq in C#.
To achive the same thing with Linq I have tried this(still "doesn't work"):
InfoAboutBothCustomers = c.customers.FirstCustomerName == c.customers.SecondCustomerName.ToString()
Note: InfoAboutBothCustomers is an int in my ViewModel
So my question basically is how do the same thing in LINQ?
I am not sure what value you want in InfoAboutBothCustomers. Your SQL statement returns two values and you are saying that you want an int. c.customers.FirstCustomerName == c.customers.SecondCustomerName.ToString() will return a boolean to say if they are equal or not.
If you want the id or ids that match you criteria, try something like:
var ids = from cust in customers
where cust.FirstCustomerName == cust.SecondCustomerName
select cust.Id;
Alternatively you can use what is mentioned in the other answers, which is cleaner, but just be aware that FirstOrDefault will return the row of data. You can then specify the column that you want by doing something like this FirstOrDefault().Id;
Without sample it is difficult to provide any solution. But you can try this
InfoAboutBothCustomers = c.customers.Where(x=>x.FirstCustomerName == x.SecondCustomerName).FirstOrDefault()
In case of error /issue please share the sample.
Use .Where operation
InfoAboutBothCustomers = c.customers.Where(c => c.FirstCustomerName == c.SecondCustomerName).FirstOrDefault();

LINQ to SQL, condition on foreign entities

In SQL, it'd be done as such:
SELECT * FROM Student
WHERE SchoolId IN
(SELECT id FROM School WHERE Name LIKE '%elementary%')
How do I implement this with LINQ? I've tried the following:
var list = context.Students.Where(x => context.Schools.Where(r => r.Name.Contains("elementary").Select(r => r.Id).Contains(x.SchoolId))
but it's not giving me what I want, unfortunately...
I know it's possible to retrieve all the Ids from the School table first, but I think it'd take a heavy toll on the performance. Preferably I'd like LINQ to SQL to handle everything; I can't do this using vanilla SQL because I need stuff to be dynamic and currently LINQ is the best solution for me.
The code above is all for illustration purposes; what I'm doing is a tad different (but more or less the same). I really do need some help on this; if you need any more information just feel free to ask.
EDIT: My bad, I missed out a field. It works, but the results didn't show up because I was missing that field... So sorry...
Try this:
var result = from st in context.Student
from sc in context.Schools
where sc.Name.Contains("elementary") && sc.SchoolId == st.SchoolId
select st;
I am a bit hazy on the syntax, pardon me. But this should point you to the right direction.
Something like this should work. The first use of Contains is on a string object to see if the string contains the substring "elementary". The second use of Contains is on a list and checks to see if the first result list contains SchoolId.
var sublist = from s in context.Schools
where s.Name.Contains("elementary")
select id;
var list = from s in context.Students
where sublist.Contains(s.SchoolId)
select s;

Sort Linq list with one column

I guess it should be really simple, but i cannot find how to do it.
I have a linq query, that selects one column, of type int, and i need it sorted.
var values = (from p in context.Products
where p.LockedSince == null
select Convert.ToInt32(p.SearchColumn3)).Distinct();
values = values.OrderBy(x => x);
SearchColumn3 is op type string, but i only contains integers. So i thought, converting to Int32 and ordering would definitely give me a nice 1,2,3 sorted list of values. But instead, the list stays ordered like it were strings.
199 20 201
Update:
I've done some tests with C# code and LinqPad.
LinqPad generates the following SQL:
SELECT [t2].[value]
FROM (
SELECT DISTINCT [t1].[value]
FROM (
SELECT CONVERT(Int,[t0].[SearchColumn3]) AS [value], [t0].[LockedSince], [t0].[SearchColumn3]
FROM [Product] AS [t0]
) AS [t1]
WHERE ([t1].[LockedSince] IS NULL)
) AS [t2]
ORDER BY [t2].[value]
And my SQL profiler says that my C# code generates this piece of SQL:
SELECT DISTINCT a.[SearchColumn3] AS COL1
FROM [Product] a
WHERE a.[LockedSince] IS NULL
ORDER BY a.[SearchColumn3]
So it look like C# Linq code just omits the Convert.ToInt32.
Can anyone say something useful about this?
[Disclaimer - I work at Telerik]
You can solve this problem with Telerik OpenAccess ORM too. Here is what i would suggest in this case.
var values = (from p in context.Products
where p.LockedSince == null
orderby "cast({0} as integer)".SQL<int>(p.SearchColumn3)
select "cast({0} as integer)".SQL<int>(p.SearchColumn3)).ToList().Distinct();
OpenAccess provides the SQL extension method, which gives you the ability to add some specific sql code to the generated sql statement.
We have started working on improving this behavior.
Thank you for pointing this out.
Regards
Ralph
Same answer as one my other questions, it turns out that the Linq provider i'm using, the one that comes with Telerik OpenAccess ORM does things different than the standard Linq to SQL provider! See the SQL i've posted in my opening post! I totally wasn't expecting something like this, but i seem that the Telerik OpenAccess thing still needs a lot of improvement. So be careful before you start using it. It looks nice, but it has some serious shortcomings.
I can't replicate this problem. But just make sure you're enumerating the collection when you inspect it. How are you checking the result?
values = values.OrderBy(x => x);
foreach (var v in values)
{
Console.WriteLine(v.ToString());
}
Remember, this won't change the order of the records in the database or anywhere else - only the order that you can retrieve them from the values enumeration.
Because your values variable is a result of a Linq expression, so that it doest not really have values until you calling a method such as ToList, ToArray, etc.
Get back to your example, the variable x in OrderBy method, will be treated as p.SearchColumn3 and therefore, it's a string.
To avoid that, you need to let p.SearchColumn3 become integer before OrderBy method.
You should add a let statement in to your code as below:
var values = (from p in context.Products
where p.LockedSince == null
let val = Convert.ToInt32(p.SearchColumn3)
select val).Distinct();
values = values.OrderBy(x => x);
In addition, you can combine order by statement with the first, it will be fine.

LINQ query help (LINQ to SQL)

I'm not really familiar with LINQ, but I'm currently working on an ASP.NET project and using LINQ to SQL as ORM (I'm building a route planning application). I have a problem creating a query the way I need it, so maybe anyone could give me a hint how to achieve this. My current query looks like this:
var results = from lift in db.Lift
where lift.StartTime > DateTime.Now
&& lift.Route.Stop.Any(o => o.Location.Name.ToLower().Contains(origin))
&& lift.Route.Stop.Any(d => d.Location.Name.ToLower().Contains(destination))
select lift;
This query works and does its work. The extension I would need is the following: each Stop has a field called Order which determines the Stop order in a specific Route. My query should select all Lifts which Route has Stops which match order and destination (thats what the query does so far) AND where the origin Stop has a lower Order number than the destination Stop. Can I do this with LINQ or do I have to filter the results afterwards?
Thanks in advance,
Mathias
Off the top of my head.. try something like this (could probably be simplified):
var results = from lift in db.Lift
let originStop = lift.Route.Stop.
FirstOrDefault(o => o.Location.Name.ToLower().Contains(origin))
let destinationStop = lift.Route.Stop.
FirstOrDefault(d => d.Location.Name.ToLower().Contains(destination))
where lift.StartTime > DateTime.Now
&& originStop != null
&& destinationStop != null
&& originStop.OrderNumber < destinationStop.OrderNumber
select lift;

LINQ to SQL Equivalent of ISDATE() in T-SQL and casting?

Does anyone know the equivalent of ISDATE() in LINQ to SQL query syntax? I've got a varchar field in SQL that contains dates and I need to filter out the non-date rows.
was hoping for something like this:
var query = SomeDataContext;
query = from p in query
where p.ISDATE(field1) == true;
select p;
also, how would one cast something for SQL in Linq syntax?
CAST(SomeDate AS SMALLDATETIME)
The trick to doing this is to create a user function in the database which merely calls ISDATE as returns the value
CREATE FUNCTION My_ISDATE(#maybeDate varchar(max))
returns bit
as return ISDATE(#maybeDate);
Then add My_IsDate to you database context, and use it in you query:
var db = SomeDataContext;
var query = from p in db.MyTable
where db.My_ISDATE(p.field1)
select p;
I don't think there is an extension method that maps to ISDATE when using LINQ to SQL.
If you are ok with loading all the data and then doing the filtering in the client space, then use TryParse on the field and compare to the date.
Otherwise, I would create a stored procedure which would return the data you want (so that you can use ISDATE), and then execute that through the context.
Also, your syntax for the use of ISDATE is incorrect. ISDATE just tells you if the expression is a valid date format. Your query would look like this:
var query = SomeDataContext;
query = from p in query
where ISDATE(field1) != 0 && CONVERT(datetime, field1) > some date
select p;
The syntax isn't valid, but it gives you an idea of how to form the query.
A problem with SO is that an increasing number of threads on answers of problems contain outdated answers, mostly because they are not touched in years. However in combination with a search engine (e.g. Google) who then returns as #1 a link (for instance this post) when you query "How should i use IsDate in Linq" it needs someone to then add one answer (at the bottom with 0 votes) of the latest correct answer.
:: https://github.com/dotnet/efcore/issues/8488 >
It now has been added to EF.Functions so you can simply do:
Where(x=> EF.Functions.IsDate(x.somefield))
Looks like you can do it. Links:
http://msdn.microsoft.com/en-us/library/bb386973.aspx
this might be of help but I haven't watched it:
http://mtaulty.com/videos/nuggets/l2s/15_mt_l2s_callingsqlfunctions.wmv
Full list here:
http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2007/05/10/9322.aspx

Categories