How do I do an inner select in linq? - c#

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();

Related

Linq select where has at least one entry in another table

I have the following structure that I wan't to query using Linq, specifically Linq to Entities (Enitity Framework).
Table1: RouteMeta
Table2: SitePage
Multiple SitePages can link to the same RouteMeta.
I'm querying the Route Meta to select a number of rows. I'm using a generic repository, currently like this:
return r.Find().ToList();
There's nothing special about it - the Find method accepts an optional linq expression, so I could do something like this:
return r.Find(x => x.Status=1).ToList();
However, what I actually want to do is to select rows from RouteMeta where at least one linked row exists in SitePages with a property IsPublished = true.
return r.Find(x => x.SitePages("where y => y.IsPublished = true");
Obviously, the above isn't correct, I'm just trying to explain the scenario better.
Any advice appreciated.
try something like
return r.Find(x=>x.Sitepages.Any(y=>y.Published))?
I'd also suggesting using a profiler if possible to check that this translates properly into SQL. It probably should do but it depends on how your repository works.

C# LINQ search by position

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.

Get First Single matched element or First if there's no match?

Is that possible in LINQ to write a nice one-liner to get a first matched element or if there's no match than get first element in the collection?
E.g. you have a collection of parrots and you want yellow parrot but if there's no yellow parrots - then any will do, something like this:
Parrots.MatchedOrFirst(x => x.Yellow == true)
I'm trying to avoid double-go to SQL Server and the ORM we use in this particular case is Dapper.
What about:
var matchedOrFirst = Parrots.FirstOrDefault(x => x.Yellow == true)
?? Parrots.FirstOrDefault();
Edit
For structs, this should work:
var matchedOrFirst = Parrots.Any(x => x.Yellow == true)
? Parrots.First(x => x.Yellow == true)
: Parrots.FirstOrDefault();
Edit: It was a linq to SQL solution
First building a handy extension
public static T MatchedOrFirstOrDefault<T>(this IQueryable<T> collection, System.Linq.Expressions.Expression<Func<T, Boolean>> predicate)
{
return (from item in collection.Where(predicate) select item)
.Concat((from item in collection select item).Take(1))
.ToList() // Convert to query result
.FirstOrDefault();
}
Using the code
var matchedOrFirst = Parrots.MatchedOrFirstOrDefault(x => x.Yellow);
If you want to avoid a 2nd SQL call and since requires branching logic, its unlikely that Dapper will know how to convert a LINQ query you come up with into appropriate SQL IIF, CASE, or whatever other SQL-specific functions you end up using.
I recommend you write a simple stored procedure to do that and call it from Dapper.
Depending on its usage though, if this page only has one or two queries on it already, and is located reasonably close (latency wise) to the server, a 2nd simple SELECT won't hurt the overall application that much. Unless it is in a loop or something, or your example is trivial compared to the actual query regarding the cost of the first SELECT.

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;

linq SingleorDefault

I want to return a single row from the users table using domain account id as my primary and unique key
However when i use singleordefault and see its sql translation it performs entire select * from Users
my query is..
var user = base.SingleorDefault(t=>t.domainaccountid)
i want this to return just one row!
What is base ? Is it possible that you've coerced it to IEnumerable<T> at some point, rather than IQueryable<T>? that would cause this. Note that database composition is only possible when using IQueryable<T>, so if any of your methods have returned something other than this, composition will end.
You could try Where along with FirstOrDefault:
var user = base.Where(t => t.domainaccountid == 123).FirstOrDefault();
Try
var user = base.SingleorDefault(t=>t.domainaccountid==123);
SingleOrDefault looks for unique entries, it should be doing:
SELECT TOP 2 * FROM TABLE
It does this so that if it finds 2 results it will throw an exception as it is not unique.
If you don't care about finding it as a unique object, as you have other measure in place to prevent duplicates; or just don't care you can use FirstOrDefault in the following way:
array.FirstOrDefault(x => x.id == someOtherId);
This will perform the following:
SELECT TOP 1 * FROM TABLE
This will get your results quicker, especially in larger tables, because it will return as soon as the first result is found.

Categories