LINQ to SQL multiple tables left outer join w/condition in 'on' clause - linq

SELECT u.username, COUNT(r.id)
FROM users u
LEFT JOIN userroles ur ON u.id = ur.userid
LEFT JOIN roles r ON ur.roleid = r.id AND r.name = 'Managers'
GROUP BY u.username
ORDER BY u.username
The goal is very simple, the above SQL runs fine, now I need to figure out how to convert it into LINQ code. I have the left joins working, the two things I don't know how to do is the count and the r.name = 'Managers'. Here is what I have so far, how do I finish it off?
var result =
from user in _context.Users
join userRole in _context.UserRoles on user.Id equals userRole.UserId into userUserRoleGroup
from u in userUserRoleGroup.DefaultIfEmpty()
join role in _context.Roles
on u.RoleId equals role.Id into roleUserRoleGroup
from r in roleUserRoleGroup.DefaultIfEmpty()
select new UserRole { Username = user.UserName, RoleName = r.Name };

You can do the count like this:
var count = from role in _context.Role
group role by role.UserId into groupedRoles
select new
{
RoleId = groupedRoles.Key,
Total = groupedRoles.Count()
}
and then you can join the variable "count" in your query.
It will have the property "Total" that is your count.

Related

Need help converting SQL into LINQ

SELECT ra.ResidentID, ra.RoomID, r.Number, ra.StartDate, p.FacilityID
FROM(
SELECT ResidentID, MAX(StartDate) AS max_start
FROM RoomAssignments
GROUP BY ResidentID
) m
INNER JOIN RoomAssignments ra
ON ra.ResidentID = m.ResidentID
AND ra.StartDate = m.max_start
INNER JOIN Rooms r
ON r.ID = ra.RoomID
INNER JOIN Person p
ON p.ID = ra.ResidentID
inner join ComplianceStage cs
ON cs.Id = p.ComplianceStageID
ORDER BY ra.EndDate DESC
I'm trying to figure out how to convert this to C# using LINQ. I'm brand new with C# and LINQ and can't get my subquery to fire correctly. Any chance one of you wizards can turn the lights on for me?
Update-----------------
I think I've got the jist of it, but am having trouble querying for the max startdate:
var maxQuery =
from mra in RoomAssignments
group mra by mra.ResidentID
select new { mra.ResidentID, mra.StartDate.Max() };
from ra in RoomAssignments
join r in Rooms on ra.RoomID equals r.ID
join p in Persons on ra.ResidentID equals p.ID
where ra.ResidentID == maxQuery.ResidentID
where ra.StartDate == maxQuery.StartDate
orderby ra.ResidentID, ra.StartDate descending
select new {ra.ResidentID, ra.RoomID, r.Number, ra.StartDate, p.FacilityID}
Following my LINQ to SQL Recipe, the conversion is pretty straight forward if you just follow the SQL. The only tricky part is joining the range variable from the subquery for max start date to a new anonymous object from RoomAssignments that matches the field names.
var maxQuery = from mra in RoomAssignments
group mra by mra.ResidentID into mrag
select new { ResidentID = mrag.Key, MaxStart = mrag.Max(mra => mra.StartDate) };
var ans = from m in maxQuery
join ra in RoomAssignments on m equals new { ra.ResidentID, MaxStart = ra.StartDate }
join r in Rooms on ra.RoomID equals r.ID
join p in Persons on ra.ResidentID equals p.ID
join cs in ComplianceStage on p.ComplianceStageID equals cs.Id
orderby ra.EndDate descending
select new {
ra.ResidentID,
ra.RoomID,
r.Number,
ra.StartDate,
p.FacilityID
};

How to use MAX in subquery in LINQ

I am trying to write my first query in LINQ
This is my SQL query
SELECT P.id,PS.Id,P.CPersonName
,PS.StartDate FROM Provider P
LEFT OUTER JOIN ProviderSubscription PS ON
P.id=PS.providerID
AND PS.Id=(SELECT max(id)from ProviderSubscription where
providerSubscription.ProviderId=Provider.id)
And so far i wrote this LINQ.
var query = (from p in db.Providers
join ps in db.ProviderSubscriptions on p.Id
equals ps.ProviderId
select new ViewModel
{
providerid = p.Id,
providername = p.ProviderName,
subscriptiondate = ps.ExpiryDate,
}).ToList();
I am unable to add this part in my LINQ.
AND PS.Id=(SELECT max(id)from ProviderSubscription where
providerSubscription.ProviderId=Provider.id)
I don't think you need a subquery, when you're doing a join with same tables and with same conditions then there is NO need to again write an inner query with same tables. Below query should return same result:
var query = (from p in db.Providers
join ps in db.ProviderSubscriptions on p.Id equals ps.ProviderId
where ps.Contains(ps.Max(u=>u.id))
select new ViewModel
{
providerid = p.Id,
providername = p.ProviderName,
subscriptiondate = ps.ExpiryDate,
}).ToList();

CRM 2011- LINQ query joining Account, Case and Activity entity

I try to make the following query using Account, Case and Activity entities :
*var findCases =
from a in context.AccountSet
join c in context.IncidentSet
on a.AccountId equals c.CustomerId.Id
join p in context.ActivityPointerSet
on c.Id equals p.RegardingObjectId.Id
select new
{
TicketNumber = c.TicketNumber,
IncidentId = c.IncidentId,
CreatedOn = c.CreatedOn,
StateCode = c.StateCode,
AccountName = a.Name
};*
The execution of this query gives the error:
AttributeFrom and AttributeTo must be either both specified or both ommited. You can not pass only one or the other. AttributeFrom: , AttributeTo: regardingobjectid
Any suggestion will be appreciated.
Regards.
Radu Antonache
Remove CasesForAccount from the query..
*var findCases =
from a in context.AccountSet
join c in context.IncidentSet
on a.AccountId equals c.CustomerId.Id
join p in context.ActivityPointerSet
on c.Id equals p.RegardingObjectId.Id
select new
{
TicketNumber = c.TicketNumber,
IncidentId = c.IncidentId,
CreatedOn = c.CreatedOn,
StateCode = c.StateCode,
AccountName = a.Name
};*

complex t-sql to linq query: inner join, group by, select

I'm trying to build a linq query based on this:
select
SERVICE_REQUEST_CR.SRCR_FK_SR, SERVICE_REQUEST.SR_TX_NAME,
AC_USER.USER_TX_NAME, SERVICE_REQUEST_CR.SRCR_DT_CREATED,
SERVICE_REQUEST_CR_STATUS.SRCRST_TX_DESCRIPTION,
COUNT(SERVICE_REQUEST_PROGRAM.SRPG_FK_SR_ID) as Activities
from
SERVICE_REQUEST_CR
inner join
AC_USER on AC_USER.USER_ID = SERVICE_REQUEST_CR.SRCR_FK_REQUESTOR
inner join
SERVICE_REQUEST_CR_STATUS on SERVICE_REQUEST_CR_STATUS.SRCRST_ID = SERVICE_REQUEST_CR.SRCR_FK_CR_STATUS
inner join
SERVICE_REQUEST on SERVICE_REQUEST.SR_ID = SERVICE_REQUEST_CR.SRCR_FK_SR
inner join
SERVICE_REQUEST_PROGRAM on SERVICE_REQUEST_PROGRAM.SRPG_FK_SR_ID = SERVICE_REQUEST_CR.SRCR_FK_SR
group by
SERVICE_REQUEST_CR.SRCR_FK_SR, SERVICE_REQUEST.SR_TX_NAME,
AC_USER.USER_TX_NAME, SERVICE_REQUEST_CR.SRCR_DT_CREATED,
SERVICE_REQUEST_CR_STATUS.SRCRST_TX_DESCRIPTION,
SERVICE_REQUEST_PROGRAM.SRPG_FK_SR_ID
This is as far as I could come up with:
Dim x = From cr In db.SERVICE_REQUEST_CR
Join usr In db.AC_USER On usr.USER_ID Equals cr.SRCR_FK_REQUESTOR
Join crSt In db.SERVICE_REQUEST_CR_STATUS On crSt.SRCRST_ID Equals cr.SRCR_FK_CR_STATUS
Join sr In db.SERVICE_REQUEST On sr.SR_ID Equals cr.SRCR_FK_SR
Join srProg In db.SERVICE_REQUEST_PROGRAM On srProg.SRPG_FK_SR_ID Equals cr.SRCR_FK_SR
Could anyone give me a help with this? It's the grouping that gets confusing so I just put the joins and the query to keep it simple.
Thanks,
Something like this, but I am not sure about Basic syntax:
Dim x = From cr In db.SERVICE_REQUEST_CR
Join usr In db.AC_USER On usr.USER_ID Equals cr.SRCR_FK_REQUESTOR
Join crSt In db.SERVICE_REQUEST_CR_STATUS On crSt.SRCRST_ID Equals cr.SRCR_FK_CR_STATUS
Join sr In db.SERVICE_REQUEST On sr.SR_ID Equals cr.SRCR_FK_SR
Join srProg In db.SERVICE_REQUEST_PROGRAM On srProg.SRPG_FK_SR_ID Equals cr.SRCR_FK_SR
group new
{
cr.SRCR_FK_SR,
sr.SR_TX_NAME,
usr.USER_TX_NAME,
cr.SRCR_DT_CREATED,
crSt.SRCRST_TX_DESCRIPTION,
srProg.SRPG_FK_SR_ID
}
by new
{
cr.SRCR_FK_SR,
sr.SR_TX_NAME,
usr.USER_TX_NAME,
cr.SRCR_DT_CREATED,
crSt.SRCRST_TX_DESCRIPTION,
srProg.SRPG_FK_SR_ID
} into gr
select new
{
gr.Key.SRCR_FK_SR,
gr.Key.SR_TX_NAME,
gr.Key.USER_TX_NAME,
gr.Key.SRCR_DT_CREATED,
gr.Key.SRCRST_TX_DESCRIPTION,
gr.Key.SRPG_FK_SR_ID,
Activities = gr.Count()
}

What is a good strategy for handling Complex Right Outer Joins in LINQ / EF

I have this Model
My goal is to retrieve all resources for a user except for resources that share a restricted role with that user.
This is not too hard in straight SQL (6BA60C09-2873-46A5-BAFB-5996A6C6482B is the userid)
SELECT distinct r.Name
FROM dbo.Resources xr
INNER JOIN [dbo].[x_Resource_RestrictedRole] rr ON xr.Id = rr.ResourceId
INNER JOIN [dbo].[aspnet_UsersInRoles] ur ON ur.RoleId = rr.RoleId
AND ur.UserId = '6BA60C09-2873-46A5-BAFB-5996A6C6482B'
RIGHT JOIN dbo.Resources r on r.id = xr.id
WHERE xr.id IS NULL
I can't figure out a good strategy for this in EF because I don't have access to the association tables.
Can this be done in LINQ or lambda expression?
You have some sort of question but I will try to answer about your query
var y = (from xr in context.Resources
join rr in context.x_Resource_RestrictedRole on xr.Id equals rr.ResourceId
join ur in context.aspnet_UsersInRoles on rr.RoleId equals ur.RoleId
join r in context.Resources on xr.id equals r.id into rJoin
from r2 in rJoin.DefaultIfEmpty()
where xr.id == null && ur.UserId = "6BA60C09-2873-46A5-BAFB-5996A6C6482B"
select new { r.Name }).Distinct(c => c.Name).ToList();

Resources