I have following values in a table and I need a LINQ query which satisfies the conditions below.
Select a single record, which has the maximum RevOrder.
If there are multiple records with same maximum RevOrder, then select the record with maximum RevDate
If RevDate's are equal too then get the record with maximum RevisionStatusID.
RevisionStatusID RevDate RevOrder
1 12/01/2012 0
2 14/02/2013 1
3 10/02/2013 2
4 11/01/2013 2
5 11/01/2013 3
I tried the below query but it gives an error.
var DocRevIDs = (from tbh in context.tblDocumentHeaders
join tbr in context.tblDocumentRevisions
on tbh.DocumentHeaderID equals tbr.DocumentHeaderID
where tbh.DocumentHeaderID == tb.DocumentHeaderID
select tbr).Max(o => new { o.RevOrder,o.RevisionDate,o.DocumentRevisionID });
Unable to process the type
'<>f__AnonymousType523[System.Nullable1[System.Double],System.Nullable`1[System.DateTime],System.Int32]',
because it has no known mapping to the value layer.
Instead of trying to use Max(), use a combination of orderby clauses and then use FirstOrDefault(). This would be the approach you would take to do it via straight SQL.
So that would give you something similar to:
var docRevision = (from tbh in context.tblDocumentHeaders
join tbr in context.tblDocumentRevisions
on tbh.DocumentHeaderID equals tbr.DocumentHeaderID
where tbh.DocumentHeaderID == tb.DocumentHeaderID
orderby tbr.RevOrder descending, tbr.RevisionDate descending, tbr.DocumentRevisionID descending
select tbr).FirstOrDefault();
you should Order the records in the linq:
var DocRevIDs = (from tbh in context.tblDocumentHeaders
join tbr in context.tblDocumentRevisions
on tbh.DocumentHeaderID equals tbr.DocumentHeaderID
where tbh.DocumentHeaderID == tbr.DocumentHeaderID
orderby tbr.RevOrder descending, tbr.RevDate descending, tbr.RevisionStatusID descending
select tbr).First();
Related
Using a SQL query within Microsoft SQL Server, I am able to get my desired results. Now I'm trying to utilize this query in my project via LINQ.
My SQL query is
SELECT distinct DeviceId, max (Head), max(Shoulder), max(Chest)
FROM EventUserOverPressure eop
JOIN UserEventInfo uei on uei.UserEventInfo_Id = eop.UserEventInfo_Id
JOIN BlastRecord br ON br.BlastRecord_Id = uei.BlastRecord_Id
JOIN WeaponsFiringLog wfl ON wfl.BlastRecord_Id = br.BlastRecord_Id
JOIN WeaponsFired wf ON wf.Blast_WFL_Id = wfl.Blast_WFL_Id
WHERE br.BlastRecord_Id = 1599
group BY DeviceId
Thus far, my LINQ query is
var myOverPressures = (from eop in db.EventUserOverPressures
join uei in ueiList on eop.UserEventInfo_Id equals uei.UserEventInfo_Id
join br in blastRecords on uei.BlastRecord_Id equals br
join wfl in weaponFiringLogss on uei.BlastRecord_Id equals wfl.BlastRecord_Id
join wf in weaponsFired on wfl.Blast_WFL_Id equals wf.Blast_WFL_Id
where (eop.Chest > 0 || eop.Head > 0 || eop.Shoulder > 0)
select new { eop.DeviceDataId, eop.Head, eop.Shoulder, eop.Chest }).Distinct().ToList();
I know the BlastRecord_Id is set to 1599 and it's a variable in LINQ. That's intentional. I was trying to figure out my query in SQL, so I focused on specific record. In LINQ it needs to work for all BlastRecord_Id's. Using LINQ, I'm able to group by DeviceDataId on the next, outside of the initial query.
My goal is to group by DeviceDataId as part of this query, and get the max values for Head Shoulder and Chest - like I did in the SQL query. If it matters, my end goal is sort my results. I know my SQL query results give me what I need in order to sort how I want. I've spent an embarrassing amount of time trying to figure this out. Any help is greatly appreciated.
Try:
var myOverPressures = (
from eop in db.EventUserOverPressures
join uei in ueiList on eop.UserEventInfo_Id equals uei.UserEventInfo_Id
join br in blastRecords on uei.BlastRecord_Id equals br.BlastRecord_Id
join wfl in weaponFiringLogss on uei.BlastRecord_Id equals wfl.BlastRecord_Id
join wf in weaponsFired on wfl.Blast_WFL_Id equals wf.Blast_WFL_Id
where (eop.Chest > 0 || eop.Head > 0 || eop.Shoulder > 0)
select new { eop.DeviceDataId, eop.Head, eop.Shoulder, eop.Chest }
)
.GroupBy(r => r.DeviceDataId)
.Select(g => new {
DeviceDataId = g.Key,
maxHead = g.Max(r => r.Head),
maxShoulder = g.Max(r => r.Shoulder),
maxChest = g.Max(r => r.Chest)
})
.ToList();
The .GroupBy() maps the data to a collection of groups, each of which has a key and a collection of group member objects. The .Select() then extracts the key and calculates the max of the Head/Shoulder/Chest values within each group.
I removed the .Distinct(), as I believe it is unnecesary due to the fact that each group key (DeviceDataId) should already be distinct.
As a side note: I noticed that the join structure of your query has what appears to be two independent one-to-many join relationships:
BlastRecord
+--> UserEventInfo --> EventUserOverPressure
+--> WeaponsFiringLog --> WeaponsFired
This may lead to the results being the cartesian product of the two join paths, yielding duplicate data. This could be a problem if you were counting of summing the effects, but if max() is the only aggregation used, I do not believe the results are affected.
I believe the grouping and aggregation may also be done in the LINQ query syntax. Something like:
var myOverPressures = (
...
group eop by eop.DeviceDataId into g
select new {
DeviceDataId = g.Key,
maxHead = g.Max(r => r.Head),
maxShoulder = g.Max(r => r.Shoulder),
maxChest = g.Max(r => r.Chest)
}
)
.ToList();
(I am not 100% sure I have this right. If someone spots an error and comments, I will correct the above.)
Try this one
var query = (from eop in db.EventUserOverPressure
join uei in db.UserEventInfo on eop.UserEventInfo_Id equals uei.UserEventInfo_Id
join br in db.BlastRecord on uei.BlastRecord_Id equals br.BlastRecord_Id
join wfl in db.WeaponsFiringLog on br.BlastRecord_Id equals wfl.BlastRecord_Id
join wf in db.WeaponsFired on wfl.Blast_WFL_Id equals wf.Blast_WFL_Id
where br.BlastRecord_Id == 1599
group eop by eop.DeviceId into g
select new
{
DeviceId = g.Key,
Head = g.Max(x => x.Head),
Shoulder = g.Max(x => x.Shoulder),
Chest = g.Max(x => x.Chest)
});
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()
};
if checkbox chkAus checked :
if (chkAus.Checked)
{
vAdvanceSearchResults = (from t in vAdvanceSearchResults
join imp in _bDataContext.Imprints on t.ImprintID equals imp.ID
join cc in _bDataContext.CountryCodes on imp.CountryID equals cc.ID
where cc.Code.Contains("AU")
select t).Distinct();**
}
if chkAus and chkNz are checked
if (chkNz.Checked && chkAus.Checked)
{
vAdvanceSearchResults = (from t in vAdvanceSearchResults
join imp in _bDataContext.Imprints on t.ImprintID equals imp.ID
join cc in _bDataContext.CountryCodes on imp.CountryID equals cc.ID
where cc.Code.Contains("AU") || cc.Code.Contains("NZ")
select t).Distinct();
}
The condition on linq query changes as the checkboxes are checked.
where cc.Code.Contains("AU") || cc.Code.Contains("NZ")
I have nearly 10 checkboxes, and got stuck on how to write that many conditions.
Any help please.
for example if there is chkUS :
then the combination with chkAus,chkNz,chkUS checkboxes the linq query would change.
where cc.Code.Contains("AU") || cc.Code.Contains("NZ") || cc.Code.Contains("US")
Put all of them in a list and then do a if list.contains(cc.Code)
var a = new List<string>(){"AU","NZ","US"};
var linq = (from t in vAdvanceSearchResults
join imp in _bDataContext.Imprints on t.ImprintID equals imp.ID
join cc in _bDataContext.CountryCodes on imp.CountryID equals cc.ID
where a.Contains(cc.Code)
select t).Distinct();
Create a list of selected checkboxes first. Like this.
var selectedCountries = new List<string>();
if (chkAus.Checked) selectedCountries.Add("AU");
if (chkNz.Checked) selectedCountries.Add("NZ");
if (chkUs.Checked) selectedCountries.Add("US");
//... And so on
And then modify your linq query to check whether this list contains the code or not, I mean reversing the comparison is an answer. Make sure you remove if condition for this linq query.
vAdvanceSearchResults = (from t in vAdvanceSearchResults
join imp in _bDataContext.Imprints on t.ImprintID equals imp.ID
join cc in _bDataContext.CountryCodes on imp.CountryID equals cc.ID
where selectedCountries.Contains(cc.Code)
select t).Distinct();
This will fix your problem.
I have a LINQ to construct a list of buildings, which has a field consisting of a list of Users:
List<Building> buildings = (from b in db.Buildings
join u in db.BuildingUsers on b.BuildingId equals u.BuildingId into bUsers
orderby b.BuildDate descending
select Building.Create(b, bUsers)).ToList();
The UserName is not always the user I want. What I really want is the first User that was ever entered, which I think is correct to assume it would be the BuildingUser with the lowest UserID. So I do the Order By:
List<Building> buildings = (from b in db.Buildings
join u in db.BuildingUsers on b.BuildingId equals u.BuildingId into bUsers
orderby u.UserId ascending
select Building.Create(b, bUsers)).ToList();
That works great, except now my overall list of buildings is in an awkward order. The bUsers is passed into the Create method in the correct order, and I handle the FirstOrDefault() to get the first user and handle the rest. I want the end-result of the overall building list to be in order by BuildDate.
List<Building> buildings = (from b in db.Buildings
join u in db.BuildingUsers on b.BuildingId equals u.BuildingId into bUsers
orderby u.UserId ascending, b.BuildDate descending
select Building.Create(b, bUsers)).ToList();
Of course this doesn't work, because now it first sorts by UserId, then by BuildDate and doesn't quite turn out correctly.
So I want one orderby for the Join, and a different orderby for the main result. I'd rather not split them into multiple methods so I don't have to alter the way I construct my building objects.
You were right in using orderby b.BuildDate descending because that is the ordering expected in your output collection buildings. The ordering of the subcollection bUsers should be performed when passing it to Building.Create():
List<Building> buildings = (from b in db.Buildings
join u in db.BuildingUsers on b.BuildingId equals u.BuildingId into bUsers
orderby b.BuildDate descending
select Building.Create(b, bUsers.OrderBy(bu => bu.UserId))).ToList();
Based on what you are saying above I might suggest changing Building.Create to accept a single user, in which case you could perform the FirstOrDefault() in this query:
List<Building> buildings = (from b in db.Buildings
join u in db.BuildingUsers on b.BuildingId equals u.BuildingId into bUsers
orderby b.BuildDate descending
select Building.Create(b, bUsers.OrderBy(bu => bu.UserId).FirstOrDefault())).ToList();
I have an SQL query that I built for a tool a while ago and I'm remaking the tool in MVC and using LINQ to Entities.
I can't seem to figure out how to sort my list of Brands by weighting my Cars by man hours and their testing value.
Here's the SQL query I had in the old tool:
SELECT Brand.ID, SUM(Car.EstManHours) - SUM(Car.EstManHours) * CAST(AVG(1.00 * TestingStatus.Value) AS DECIMAL(9 , 2)) / 100 AS Weighting
FROM TestingStatus INNER JOIN Car ON TestingStatus.ID = Car.StatusID
INNER JOIN Team ON Car.TeamID = Team.TeamID
RIGHT OUTER JOIN Brand
LEFT OUTER JOIN SubCategory ON Brand.ID = SubCategory.BrandID ON Car.SubCategoryID = SubCategory.ID
WHERE (Car.IsPunted == 'False')
GROUP BY Brand.YearID, Brand.FeatID
HAVING (Brand.YearID = #BrandYearID)
ORDER BY Weighting DESC
I've tried this, but whether I put descending or ascending the order doesn't actually change in the list, it keeps the sorting by Id:
var brands = (from b in _context.Brands
join s in _context.SubCategorys on f.Id equals s.BrandId
join c in _context.Cars on s.Id equals c.SubCategoryId
where (f.YearId == yearId && c.IsPunted == false)
orderby (c.ManHoursEst - (c.ManHoursEst * c.TestingStatu.Value / 100)) descending
select b).Distinct().ToList();
Would appreciate help on this conversion!
Thanks.
EDIT:
I'm now trying to get the order by and group by to work correctly.
The following query is listing tons of duplicates and not ordering properly as I don't think my weighting is done correctly.
var brands = (from b in _context.Brands
join s in _context.SubCategorys on f.Id equals s.BrandId
join c in _context.Cars on s.Id equals c.SubCategoryId
where (f.YearId == yearId && c.IsPunted == false)
let weighting = c.ManHoursEst - (c.ManHoursEst * c.TestingStatu.Value / 100)
orderby weighting descending
group b by b.Id).SelectMany(x=>x).ToList();
Any ideas?
Distinct does not preserve sorting. That is your problem.
You could do a group by like in your SQL to mimic the Distinct and perform everything server side.