Linq- Join, Max(Date) - c#

I'm struggling with converting SQL query to LINQ
SELECT * FROM Log x
JOIN (SELECT p.objId,
MAX(modifiedDateTime) AS latestDateTime
FROM Log p
GROUP BY p.objId) y ON y.objId= x.objId
AND y.latestDateTime = x.modifiedDateTime
Please suggest. This is where I got so far
var query1 = from x in query
join y in query
on new {x.objId, x.modifiedDateTime}
equals new {y.objId, ...(Max)}

the two new anonymous objects you create won't ever be equal. You need to compare the values to one another directly. Try:
on x.objID equals y.objID && x.modifiedDateTime equals y.lastestDateTime

Related

How to translate SQL to LINQ with individual field joins?

I have a SQL statement, that I want to implement in a .NET website project. I don't understand how to join in a particular field, as the fields aren't available when I just select from the table.
My SQL
SELECT *
FROM [vResidence] c
JOIN [vJobs] j on c.UID = j.UID
This is the LINQ I have tried, but I am stuck at the 'ON' part:
results = (from j in vJobs
join cr in vResidence on ??? )
When I try 'j.', the only option I get is 'equals'.
You can follow as this.connect to tables as JOIN use equals keyword
var result = from r in vResidence
join j vJobs on r.UID equals j.UID
select new {[yourcolnum]};
You can try this
var result = (from j in vJobs
join cr in vResidence
on j.UID equals cr.UID
select new {
...
}).ToList();
The Linq expression is the following:
from t1 in Table1
join t2 in Table2
on t1.ID equals t2.ID
The join clause on must be do in order: first the first table, then the second.
The keyword equals must be use.
Apart from the above Linq answers, we can do JOIN using Enumerable.Join extension with Lambda expressions. Try something like,
var result = vJobs.Join(vResidence, jb => new { jb.UID }, res => new { res.UID },
(jb, res) => new { jb, res })
.Select(x => x.jb) //Select the required properties (from both objects) with anonymous object or select left/right object
.ToList();
C# Fiddle with sample data.

Fluent LINQ query with multiple join conditions, one of which being a simple equals and another a less than comparison between ids

I have a SQL query which includes a left join and a group by- so far so good- my trouble arises from one of the join conditions not being a straight "equals to" and I'm lost where to go with LINQ.
I know multiple join conditions usually involves creating a couple of anonymous objects and comparing them, but when I add an "equal to" and "a greater" than into the mix, I've no idea how that applies.
Here's what I'd like the query to look like if I had invented LINQ, but I know the "and" in my join condition is invalid;
var query =
from csp in db.ChatSessionPersons
join cm in db.ChatMessages on
csp.ChatSessionId equals cm.ChatSessionId
and cm.Id > csp.LastReadChatMessageId
// (i know these should be the other way round,
// but for readability I present them like this!)
into j1
from j2 in j1.DefaultIfEmpty()
group j2 by csp.ChatSessionId into grouped
select new {
ChatSessionId = grouped.Key,
UnreadCount = grouped.Count(t => t.Id != null)};
Any ideas anyone?
You can convert the non-equality condition to a lambda Where on the group join result.
var query = from csp in db.ChatSessionPersons
join cm in db.ChatMessages on csp.ChatSessionId equals cm.ChatSessionId into cmj
select new {
ChatSessionId = csp.ChatSessionId,
UnreadCount = cmj.Where(cm => cm.Id > csp.LastReadChatMessageId).Count()
};
NOTE: I modified the query a bit to remove the group by which isn't needed if you are using a group join that has already grouped the matching results, and to remove the left join DefaultIfEmpty which also isn't needed when processing a group join with something like Count, unless you wanted to return an UnreadCount of 1 when there are no matches, in which case you should put DefaultIfEmpty() before Count().
Of course, you could use query comprehension in the sub-query:
var query = from csp in db.ChatSessionPersons
join cm in db.ChatMessages on csp.ChatSessionId equals cm.ChatSessionId into cmj
select new {
ChatSessionId = csp.ChatSessionId,
UnreadCount = (from cm in cmj where cm.Id > csp.LastReadChatMessageId select cm).Count()
};

LINQ - query on query results (some complex one)

Need some help in writing LINQ from the following SQL.
The main problem is double grouping.
I'm stacked in the second grouping
group by s.[e-year], s.[e-month]
Don't know how to implement.
Thanks a lot.
select s.[e-year], s.[e-month], count(s.projectid) 'projects entranced',
---------------------------------------------
(select count(subquery.CustomerTypeID) from
(select count(ap.ProjectID) as 'count', c.CustomerTypeID FROM Logging_ProjectsEntrances] pe
inner join users u on pe.userid = u.userid
inner join Companies c on u.CompanyId = c.CompanyID
inner join AssignedProjects up on pe.ProjectID = up.ProjectID
inner join Projects p on up.ProjectID = p.ProjectID
where ap.ProductID = 1 and year(pe.EntranceDate) = s.[e-year] and MONTH(pe.entrancedate) = s.[e-month] and c.CustomerTypeID = 2
group by ap.ProjectID, c.CustomerTypeID) subquery
group by subquery.CustomerTypeID
)
--------------------------------------------
from
(
select YEAR(pe.EntranceDate) as 'e-year', MONTH(pe.EntranceDate) as 'e-month', up.ProjectID as 'projectid'
FROM Logging_ProjectsEntrances pe
inner join AssignedProjects ap on pe.ProjectID = ap.ProjectID
inner join Projects p on ap.ProjectID = p.ProjectID
where ap.ProductID = 1
group by year(pe.EntranceDate), month(pe.EntranceDate), ap.ProjectID
) as s
group by s.[e-year], s.[e-month]
order by s.[e-year] desc , s.[e-month] desc
For translating SQL to LINQ query comprehension:
Translate FROM subselects as separately declared variables.
Translate each clause in LINQ clause order, translating monadic operators (DISTINCT, TOP, etc) into functions applied to the whole LINQ query.
Use table aliases as range variables. Use column aliases as anonymous type field names.
Use anonymous types (new { ... }) for multiple columns.
Left Join is simulated by using a into join_variable and doing another from from the join variable followed by .DefaultIfEmpty().
Replace COALESCE with the conditional operator and a null test.
Translate IN to .Contains() and NOT IN to !...Contains()
SELECT * must be replaced with select range_variable or for joins, an anonymous object containing all the range variables.
SELECT fields must be replaced with select new { ... } creating an anonymous object with all the desired fields or expressions.
Proper FULL OUTER JOIN must be handled with an extension method.
Note: Your SQL query is using a SQL trick (SELECT x ... GROUP BY x) to perform the equivalent of a DISTINCT, which should be used as it expresses the intent more clearly.
So, for your SQL query:
var subq = (from pe in projectsEntrances
join ap in assignedProjects on pe.ProjectID equals ap.ProjectID
join p in projects on ap.ProjectID equals p.ProjectID
where ap.ProductID == 1
select new { e_year = pe.EntranceDate.Year, e_month = pe.EntranceDate.Month, ap.ProjectID }).Distinct();
var ans = from s in subq
group s by new { s.e_year, s.e_month } into sg
orderby sg.Key.e_year descending, sg.Key.e_month descending
select new { sg.Key.e_year, sg.Key.e_month, ProjectsEntranced = sg.Count() };

Concatenating a LINQ (To SQL) Query

I am building a LINQ query, which will have comparisons attached to the 'where' section (the number of these comparisons depends on the user's selections).
In the code-behind, I want something like this:
var builtQuery =
from q in dc.Leads
join sr in dc.SalesReps on q.SalesRepID equals sr.SalesRepID
join co in dc.Companies on q.CompanyID equals co.CompanyID
join or in dc.Origins on q.OriginID equals or.OriginID
join pr in dc.Products on q.ProductID equals pr.ProductID
where
Here, in between the 'from' and 'select' parts, I will add a number of comparisons (depending on the user's selection of checkboxes).
And Finally:
select new { q.Ref, sr.Rep, q.Deposit, q.Sale, q.Title, q.Names, q.Surname, q.HomePhone, q.WorkPhone, q.Mobile, q.Address, q.Suburb, q.County, q.Postcode, co.CompanyName, or.OriginName, pr.ProductName, q.Telemarket, q.Entered };
In PHP (using MySQL) I could simply concatenate a number of strings, which make up the query. But, in c#/LINQ To SQL, the query is not a string and so I have no idea how to do this...There were a couple similar questions on SO, but they're not quite the same thing.
Any ideas??
Thanks!
I would do it in the following way
var intermediateQuery=
from q in dc.Leads
join sr in dc.SalesReps on q.SalesRepID equals sr.SalesRepID
join co in dc.Companies on q.CompanyID equals co.CompanyID
join or in dc.Origins on q.OriginID equals or.OriginID
join pr in dc.Products on q.ProductID equals pr.ProductID
select new { q.Ref, sr.Rep, q.Deposit, q.Sale, q.Title, q.Names, q.Surname, q.HomePhone, q.WorkPhone, q.Mobile, q.Address, q.Suburb, q.County, q.Postcode, co.CompanyName, or.OriginName, pr.ProductName, q.Telemarket, q.Entered };
and then add some filters considering user input
if(SomeUserProductFilter)
{
var result = intermediateQuery.Where(p=>p.ProductName = 'UserProductName');
}
Do not be afraid that this approach will retrieve all data and than filters it in memory. LINQ sends query to database only when you call ToList(), ToArray() or use result in foreach loop

Selecting the whole data after joining in linq

When I need to join some tables using linq, and when those tables consist of a lot of fields, it takes a lot of work to get all the data that I need. For instance:
var result = from i in Person
join y in Works
on i.PID euqals y.PID
join z in Groups
on y.GID on z.GID
select new {Name = i.Name, Work = y.work, WG = z.GroupName};
How can make the query return all the tables ?
I guess what you need is simply this :
var Query = from x in Table_1
join y in Table_2
on x.id equals y.id
where x.Country.Equals("X Country")
select new {x,y};

Categories