Get TOP5 records from each status using Linq C# - c#

I have a VacancyApply table and that table consist of Status Id's,So i need Top5 data from each Status.I want to get top 5 records of each status.Status is int like 1,2,3
My Query
var result = (from ui in _context.VacancyApply
join s in _context.UserProfile on ui.UserId equals s.UserId
join x in _context.Vacancy on ui.VacancyId equals x.VacancyId
join st in _context.Status on ui.StatusId equals st.StatusId
where ui.UserId == userId && ui.IsActive == true
orderby ui.StatusId
select new VacancyApply
{
VacancyApplyId = ui.VacancyApplyId,
VacancyId = ui.VacancyId,
UserId = ui.UserId,
StatusId = ui.StatusId,
VacancyName = x.VacancyName,
VacancyStack = x.VacancyStack,
VacancyEndDate = x.VacancyEndDate,
StatusName = st.StatusName,
UserName = s.FirstName
}).ToList();

Now what I can see from the output is that it contains One VacancyId and One VendorId.
I have a feeling that you have Many to Many relationships between Vacancy and Status tables.
But nevertheless, the answer is very simple: you need to use LINQ Take extension method (maybe it will be good to make it follow after the OrderBy because just taking the last items doesn't make sense without some logic):
var output = (logic to join, filter, etc.).OrderBy(lambda).Take(N); // N is the number of
// items you want to select
Now if you want Generally to take the last items from Vacancy and only after join it with Status do this:
var output = Vacancy.OrderBy(lambda).Take(N).(now join, filter, etc. with other tables);
However, if you want to Group all similar Statuses in conjunction with Vacancies and only after taking the Top items, use GroupBy:
var output = (logic to join, filter, etc.).GroupBy(st => st.StausId).
.Select(group => group.OrderBy(lambda).Take(N));

Related

Take any single record if matching records not available - Linq

I have linq query which has multiple records & I am filtering these records using a where clause.
Now, if the filtered records return nothing then I need to make it default to take default any single record from list.
var resultStaffGua = (from s in _db.Students
join sg in _db.StudentStaffGuardians on s.StudentID equals sg.StudentId
join g in _db.Staffs on sg.StaffId equals g.StaffID
join lr in _db.luRelationTypes on sg.RelationTypeId equals lr.RelationTypeID
join ga in _db.StaffAddresses on g.StaffID equals ga.StaffID
join ad in _db.Addresses on ga.AddressID equals ad.AddressID
where
lse.StatusID == (int?)Extension.StatusType.Active
&& lse.TenantID == tenantid
select new
{
g.FirstName,
g.LastName,
IsPrimary = sg.IsPrimaryGuardian,
se.Email,
Phone = sphon.PhoneNumber,
lr.RelationCD,
gdnr.GenderCD,
ad.Zipcode
}).Where(i=>i.IsPrimary==true);
if resultStaffGua count 0, I need one record from resultStaffGua. Thank you
if result count 0, I need one record from parentList.
Sometimes the obvious solution is the best. Why not add this after your code?
if (resultStaffGua.Count() == 0)
{
resultStaffGua = parentList.First();
}
If you want to be "clever" and do it all in one line (and I guess it would save a DB transaction too possibly) you could exchange your Where for an OrderBy and a Take.
So instead of:
).Where(i=>i.IsPrimary==true);
You could do:
).OrderBy( i => i.IsPrimary ? 0 : 1 ).Take(1);
This will prioritize any record that has an IsPrimary set to true, but it'll get one record regardless of whether any match.
Assuming that your intent is to retrieve one single record (there's at most one record with IsPrimary==true):
var query = (from s in...); //The whole query except the "where"
var resultStaffGua = query.SingleOrDefault(i=>i.IsPrimary==true) ?? query.First();
Otherwise, if the query could actually return more than one result:
var query = (from s in...);
var resultStaffGua = query.Where(i=>i.IsPrimary==true);
if(resultStaffGua.Count() == 0) resultStaffGua = new[] { query.First(); }

Entity Framework - slow query after adding group by

I have a following query which runs very fast:
var query =
(from art in ctx.Articles
join phot in ctx.ArticlePhotos on art.Id equals phot.ArticleId
join artCat in ctx.ArticleCategories on art.Id equals artCat.ArticleId
join cat in ctx.Categories on artCat.CategoryId equals cat.Id
where art.Active && art.ArticleCategories.Any(c => c.Category.MaterializedPath.StartsWith(categoryPath))
orderby art.PublishDate descending
select new ArticleSmallResponse
{
Id = art.Id,
Title = art.Title,
Active = art.Active,
PublishDate = art.PublishDate ?? art.CreateDate,
MainImage = phot.RelativePath,
RootCategory = art.Category.Name,
Summary = art.Summary
})
.AsNoTracking().Take(request.Take);
However, if I add group by and change query to following statement, it runs much much slower.
var query =
(from art in ctx.Articles
join phot in ctx.ArticlePhotos on art.Id equals phot.ArticleId
join artCat in ctx.ArticleCategories on art.Id equals artCat.ArticleId
join cat in ctx.Categories on artCat.CategoryId equals cat.Id
where art.Active && art.ArticleCategories.Any(c => c.Category.MaterializedPath.StartsWith(categoryPath))
orderby art.PublishDate descending
select new ArticleSmallResponse
{
Id = art.Id,
Title = art.Title,
Active = art.Active,
PublishDate = art.PublishDate ?? art.CreateDate,
MainImage = phot.RelativePath,
RootCategory = art.Category.Name,
Summary = art.Summary
})
.GroupBy(m => m.Id)
.Select(m => m.FirstOrDefault())
.AsNoTracking().Take(request.Take);
Homepage calls query 9 times for each category. With the first version of query, without caching turned on and connecting to SQL remotely, page load is around 1.5 seconds, which makes it almost instant when application is on server, but second way makes homepage load around 39 seconds when SQL is remotely.
Can it be fixed without rewriting the entire query in to the view or stored procedure?
Grouping is an expensive operation on the database end. Without knowing what your database looks like and what indexes you've setup, it will be difficult to determine. Why not just group on the client side after the data has arrived (assuming its not an overwhelming amount).
This question explains how.
Group by in LINQ

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};

Grouping a many relationship in LINQ

I've got the following code:
var preGroup =
from l in e.WorkOrderRequests
join w in e.WorkOrders on l.WorkOrderRequestKey equals w.WorkOrderRequestKey into lw
from l2 in lw.DefaultIfEmpty()
select new { l.WorkOrderRequestStatusKey,
l.WorkOrderRequest_Status.Status,
w.Property.Address.StateKey,
w.Property.Address.MetroKey };
The relationship structure is that a Work Order Request can have many Work Orders, so it is a 1 to many relationship. I want to do a select so that each work order request will show up for as many times as there are work orders attached to it. But also it still should appear if there are no work orders attached. So a left outer join makes sense. The select above doesn't work, but that shows the data that I want to select. I need to then group this data:
var workOrderRequests =
(from l in preGroup.ToList()
group l by new { l.WorkOrderRequestStatusKey, l.Status, l.StateKey, l.MetroKey } into g
select new DashboardView
{
StatusKey = g.Key.WorkOrderRequestStatusKey,
StatusName = g.Key.Status,
StateKey = g.Key.StateKey,
MetroKey = g.Key.MetroKey,
Count = g.Count()
});
I can't get to the grouping because my preGroup query is not working. I have been able to accomplish this for other things, but those are all 1 to 1 relationships. Any help is much appreciated.

Get the "latest" datetime from a large linq query that currently returns every record that has a datetime

I have a fairly long linq query and everything works as it should.. but in a final join i am doing an innerjoin on a table that has a log, the log returns more than 50 records, i just want the latest record..
Here is an example
var tst = from w in context.storage
join p in context.products on w.id equals p.wid
join l in context.logger on p.id equals l.pid
select new
{
storageid = w.id,
productid = p.id
productname = p.name
bought = l.when
};
So a quick explanation of what happens, each product is stored in a storage center and there is a log when that product was bought, if it was bought 100 times then there is 100 records in the logger.
So currently it returns 50 records for productid = 5 ... why .. because it was bought 50 times but i only want 1 record, hence i only want the latest date time for from the logger.
Can anyone help? I am a little stuck.
Use result.Distinct(x => x.Prop) to get unique entries only
Use result.Max(x => x.Prop) to get latest date, and Min() to get earliest.
This is a case where you want to restrict to collection of records on which to join, which you can do by coding the join manually (sort of):
from w in context.storage
join p in context.products on w.id equals p.wid
// "manual" join:
from l in context.logger.Where(l => l.pid == p.id).OrderByDescencing(l => l.when).Take(1)
select new
{
storageid = w.id,
productid = p.id
productname = p.name
bought = l.when
};
In fluent linq syntax this is a SelectMany with a result selector.

Categories