I am trying to convert my program from ADO to Entity Framework and Linq. Can someone show me how to write this using Linq?
SELECT a.[Category], [WorkOrderVersion], min(a.[CategoryStartDate]) AS CategoryStartDate,
max(a.[CategoryEndDate]) AS CategoryEndDate, c.[HexColor] AS CustomBackgroundColor
FROM [Job].[EstimateTbl] as a
Left JOIN [Employee].[EmployeeColorPrefsTbl] c
ON c.[Item] = a.[Category] AND c.[EmployeeID] = #employeeID
Where [ID_Job] = #ID_Job
group by [Category], [WorkOrderVersion], c.[HexColor]
ORDER BY [Category]
I am close, but I'm not getting the grouping and Max/Min part...
var query = from a in db.EstimateTbls
where a.ID_Job == objActiveJobClass.ID
join c in db.EmployeeColorPrefsTbls on a.Category equals c.Item into ps
from c in ps.DefaultIfEmpty()
orderby a.Category ascending
select new
{
a.Category,
a.WorkOrderDate,
CategoryStartDate = a.CategoryStartDate,
CategoryEndDate = a.CategoryEndDate,
c.HexColor,
};
var query = (from a in db.EstimateTbls.Where(x=>x.ID_Job==objActiveJobClass.ID)
join c in db.EmployeeColorPrefsTbls.Where(x=>x.EmployeeID==#employeeID)
on a.Category equals c.Item
into ps1
from ps in ps1.DefaultIfEmpty()
select new{a,ps}).ToList()
.GroupBy(x=>new{x.a.Category,x.a.WorkOrderVersion,HexColor=x.ps?.HexColor})
.Select(x=>new
{
Category=x.Key.Category,
WorkOrderVersion=x.Select(z=>z.a.WorkOrderVersion).FirstOrDefault(),
CategoryStartDate=x.Min(z=>z.a.CategoryStartDate),
CategoryEndDate=x.Max(z=>z.a.CategoryEndDate),
CustomBackgroundColor=x.Key.HexColor
})
.OrderBy(x=>x.Category)
.ToList();
var query = from a in db.EstimateTbls
where a.ID_Job == objActiveJobClass.ID
join c in db.EmployeeColorPrefsTbls on a.Category equals c.Item
group new { a, c} by new { a.Category, a.WorkOrderVersion, a.CategoryStartDate, a.CategoryEndDate, c.HexColor } into g
orderby g.Key.Category ascending, g.Key.WorkOrderVersion
select new
{
Count = g.Count(),
g.Key.Category,
g.Key.WorkOrderVersion,
g.Key.CategoryStartDate,
g.Key.CategoryEndDate,
CustomBackgroundColor = g.Key.HexColor,
};
APP.1 (2) 7/26/2018 12:00:00 AM, 7/31/2018 12:00:00 AM, #FFFFA500
CAB.1 (6) , , #FF00FF00
CLN.1 (126) , , #FF7FFFD4
DMO.1 (5) 8/1/2018 12:00:00 AM, 8/5/2018 12:00:00 AM, #FFFF0000
DMO.2 (1) 8/5/2018 12:00:00 AM, 8/10/2018 12:00:00 AM, #FFFF0000
Related
So let's say we have these two tables:
CARS
ID CAR_MODEL
11 Mustang
22 Camaro
33 F-150
PARTS
ID CAR_ID PART_NAME
1 11 Steering Wheel
2 22 Steering Wheel
3 22 Headlights
NOTE: there is no foreign key relationship in the database between the PARTS.CAR_ID and CARS.ID columns.
Without the foreign key, what sort of linq query would be used to obtain these results:
CARS
ID CAR_MODEL PART_NAME_LIST
11 Mustang Steering Wheel
22 Camaro Steering Wheel, Headlights
33 F-150 (null)
Environment: SQL Server 2014, linq-to-sql
edit: here is what I have so far, but this results in 4 rows in the results (2 for Camaro), instead of 3, and it does not include any parts.
from C in db.CARS
join P in db.PARTS on C.ID equals P.CAR_ID
select new{
ID = C.ID,
CAR_MODEL = C.CAR_MODEL,
PART_NAME_LIST = ???
}
Here is a fluent syntax group join:
var sub = (from C in db.CARS
join P in db.PARTS on C.ID equals P.CAR_ID into Pj
select new {
C.ID,
C.CAR_MODEL,
PART_NAMES = from p in Pj select p.PART_NAME
})
.AsEnumerable();
var ans = from icp in sub
select new {
icp.ID,
icp.CAR_MODEL,
PART_NAME_LIST = String.Join(", ", icp.PART_NAMES)
I would probably switch to lambda syntax in the select in my code:
var ans = (from C in db.CARS
join P in db.PARTS on C.ID equals P.CAR_ID into Pj
select new {
C.ID,
C.CAR_MODEL,
PART_NAMES = Pj.Select(cpj => cpj.PART_NAME)
})
.AsEnumerable()
.Select(icp => new {
icp.ID,
icp.CAR_MODEL,
PART_NAME_LIST = String.Join(", ", icp.PART_NAMES)
});
For concatenating strings you have to use string.Join. The easiest way to do that is in a subquery:
(
from c in db.CARS
select new
{
ID = c.ID,
CAR_MODEL = c.CAR_MODEL,
PART_NAME_LIST = db.PARTS
.Where(p => c.ID equals p.CAR_ID)
.Select(p => p.PART_NAME)
}
).AsEnumerable()
.Select(c => new
{
ID = c.ID,
CAR_MODEL = c.CAR_MODEL,
PART_NAME_LIST = string.Join(", ", cPART_NAME_LIST)
})
Entity Framework doesn't support string.Join, so you have to split the query in a part that EF can translate into SQL and a part that's executed in memory, separated by AsEnumerable().
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
};
I am unable to execute the below linq.
var items( from p in Patients
join q in MURWorksheets on p.PatientId equals q.PatientId into step1
from s in step1.DefaultIfEmpty()
join t in MURWorksheetAnswers on s.MURWorksheetId equals t.MURWorksheetId into step2
from s2 in step2.DefaultIfEmpty()
select new {p.FirstName , Date = (s.MURDate == null ? DateTime.Now.Date : s.MURDate),
s2.MURQuestionnaireId,s2.MURExpctedAnswersId}).ToList();
Here is the sql for the same for your reference.
select a.FirstName,b.MURDate,c.MURQuestionnaireId,c.MURWorksheetAnswersID from Patients as a
left join MURWorksheet as b on a.PatientId = b.PatientId
left join MURWorksheetAnswers as c on b.MURWorksheetId = c.MURWorksheetId
You are missing an equals sign in your pasted code:
var items = (from p in Patients
join q in MURWorksheets on p.PatientId equals q.PatientId into step1
from s in step1.DefaultIfEmpty()
join t in MURWorksheetAnswers on s.MURWorksheetId equals t.MURWorksheetId into step2
from s2 in step2.DefaultIfEmpty()
select new {p.FirstName , Date = (s.MURDate == null ? DateTime.Now.Date : s.MURDate),
s2.MURQuestionnaireId,s2.MURExpctedAnswersId}).ToList();
I'm trying to create a Linq query for EF that joins on 2 values from an inner select. Underneath you will find the SQL query that does the trick, things are much more tricky when trying to do so in Linq.
I use POCO object and would like the query to return the List and not an anonymous type. Is this possible with Linq to EF?
SELECT s1.*
FROM [Statistics] s1
INNER JOIN
(
SELECT MAX(CreateDate) as createdate
FROM [Statistics]
GROUP BY UserId
) s2
ON s1.UserId = s2.[UserId] and s1.CreateDate = s2.createdate
ORDER BY s1.Balance desc
You can do this with a Where or a Join.
from s1 in Statistics
join s2 in (from s in Statistics group s by s.UserId into g
select new { UserId = g.Key, CreateDate = g.Max (s => s.CreateDate) })
on new { s1.UserId, s1.CreateDate } equals new { s2.UserId, s2.CreateDate }
orderby s1.Balance descending
select s1;
Or,
from s1 in Statistics
from s2 in (from s in Statistics group s by s.UserId into g
select new { UserId = g.Key, CreateDate = g.Max (s => s.CreateDate) })
where s1.UserId == s2.UserId && s1.CreateDate == s2.CreateDate
orderby s1.Balance descending
select s1;
I have a query in Oracle which i am trying to convert into linq. I think I am almost there. Here is the query in Oracle. I had quick problem with left outer joins in the query. Please consider this too in the question. My main problem is I can't write using this count, distinct for different columns in the table.
SELECT COUNT(DISTINCT claimant_id || rqst_wk_dt || claim_id) AS no_of_weeks_compensated
, SUM(pmt_am) AS total_payments
, COUNT(DISTINCT claimant_id || claim_id)
FROM (SELECT c.claimant_id
, c.claim_id
, c.rqst_wk_dt
, a.pmt_am
FROM ui_mon_hdr d
INNER JOIN ui_rqst_wk_ctrl c
ON d.claimant_id = c.claimant_id
AND d.claim_id = c.claim_id
LEFT OUTER JOIN ui_dstb_pmt a
ON c.claimant_id = a.claimant_id
AND c.claim_id = a.claim_id
AND c.rqst_wk_dt = a.rqst_wk_dt
AND a.rcpnt_id = 'CLMNT'
LEFT OUTER JOIN ui_claim_pmt b
ON c.claimant_id = b.claimant_id
AND c.claim_id = b.claim_id
AND warrant_dt BETWEEN '1 June 2011' AND '30 June 2011'
AND b.status_cd = 'PAID'
AND a.rcpnt_id = b.rcpnt_id --AND A.PMT_NU = B.PMT_NU
LEFT OUTER JOIN ui_auth_pmt e
ON c.claimant_id = e.claimant_id
AND c.claim_id = e.claimant_id
AND c.rqst_wk_dt = e.rqst_wk_dt
AND d.mon_seq_nu = e.mon_seq_nu
WHERE c.rqst_wk_dt BETWEEN '1 June 2011' AND '30 June 2011'
AND d.bspd_type_cd = 'ALTR')
Above is the query which I have in Oracle and run in TOAD. Below is the query in LINQ. I have just done internal select statement and I wonder how to implement the select count and distinct for the query:
var enddate = Convert.ToDateTime("6/30/2011");
var Altquery = from D in UiMonHdr
join C in UiRqstWkCtrl on new {D.ClaimantId, D.ClaimId} equals new {C.ClaimantId, C.ClaimId}
join A in UiDstbPmt on new {C.ClaimantId, C.ClaimId , C.RqstWkDt} equals new {A.ClaimantId, A.ClaimId, A.RqstWkDt}
where A.RcpntId.Contains("CLMNT")
join B in UiClaimPmt on new {C.ClaimantId, C.ClaimId, A.RcpntId} equals new {B.ClaimantId, B.ClaimId, B.RcpntId}
where B.StatusCd.Contains("PAID") && B.WarrantDt >= startdate && B.WarrantDt <= enddate
join E in UiAuthPmt on new {C.ClaimantId, C.ClaimId , C.RqstWkDt} equals new {E.ClaimantId, E.ClaimId, E.RqstWkDt}
where C.RqstWkDt >= startdate && C.RqstWkDt <= enddate && D.BspdTypeCd.Contains("ALTR")
select new {ClaimantId = C.ClaimantId, ClaimId = C.ClaimId, PmtAmt = A.PmtAm, RqstWkDt = C.RqstWkDt}; Altquery.Dump();