Linq Join queries - linq

Can someone refactor my code in a simpliest way?
var yearly = context.Prospects.Join(context.Prospect_Details, prospect => prospect.ProspectId,
prosDetail => prosDetail.ProspectID,
(prospect, prosDetail) => new {Prospect = prospect, ProspectDetail = prosDetail})
.Join(context.Sources, prospect => prospect.Prospect.SourceId, source => source.SourceId, (prospect, source) => new {Prospect = prospect, Source = source})
.Where(
c =>
c.Prospect.Prospect.Customer.StoreId == storeid && c.Prospect.ProspectDetail.IsDeleted == false
&& c.Prospect.ProspectDetail.DateCreated.Year == date.Year && c.Prospect.Prospect.Customer.IsMerge == null
&& c.Prospect.Prospect.SubStatus.Status.Name == "Sold").ToList();
var daily = context.Prospects.Join(context.Prospect_Details, prospect => prospect.ProspectId,
prosDetail => prosDetail.ProspectID,
(prospect, prosDetail) => new { Prospect = prospect, ProspectDetail = prosDetail })
.Join(context.Sources, prospect => prospect.Prospect.SourceId, source => source.SourceId, (prospect, source) => new { Prospect = prospect, Source = source })
.Where(
c =>
c.Prospect.Prospect.Customer.StoreId == storeid && c.Prospect.ProspectDetail.IsDeleted == false
&& c.Prospect.ProspectDetail.DateCreated.Year == date.Year && c.Prospect.ProspectDetail.DateCreated.Month == date.Month
&& c.Prospect.ProspectDetail.DateCreated.Day == date.Day && c.Prospect.Prospect.Customer.IsMerge == null
&& c.Prospect.Prospect.SubStatus.Status.Name == "Sold").ToList();
i need to know if there's a simplest way, im newbie in linq-sql.

Related

How do I exclude certain parts of a .Include on a condition?

We are trying to exclude certain data from our queries based on a condition, but we can't seem to get it right. Our current code looks like this:
var PullData = _context.RequestInformation.Include(x => x.RequestMinistry)
.Include(x => x.RequestApps)
.ThenInclude(x => x.RequestAppDataChoices)
.Where(x => x.RequestStatus != "Cancelled With Reason")
.Where(y => y.RequestApps.SelectMany(x => x.RequestAppDataChoices)
.Where(s => s.AppDataChoiceDl.Contains(groupName))
.Where(a => a.RequestApps.AppProvisioningCompleteTime != null)
.Where(aa => aa.RequestApps.AppTeamCompleteTime == null)
.Where(ab => !ab.RequestApps.AppStatus.Contains("Rejected")).Any());
This is fine as long as we are trying to pull all of the "RequestApps" with each set of "RequestInformation", however if we want to pull just specific applications based on conditions, it doesn't work. We want to only show the request apps based on the the conditions above (The appdatachoicedl contains "groupname", the completetime != null while the other completetime IS null, and that the status is not rejected), but instead, we are getting all the request information that matches those conditions.
I tried something like this, but it still doesn't quite give me the results I need. It gives me random blank results as well:
var PullDataV2 = from reqInfo in _context.RequestInformation
join RA in _context.RequestApps on reqInfo.ReqNum equals RA.ReqNum
join RADC in _context.RequestAppDataChoices on RA.PkId equals RADC.RequestAppsId
where RADC.AppDataChoiceDl == groupName
select new RequestInformation()
{
ProvisioningCompleteTime = reqInfo.ProvisioningCompleteTime,
RequestMinistry = reqInfo.RequestMinistry,
RequestApps = reqInfo.RequestApps,
UserFirstName = reqInfo.UserFirstName,
UserLastName = reqInfo.UserLastName,
SubmitterFirstName = reqInfo.SubmitterFirstName,
SubmitterLastName = reqInfo.SubmitterLastName,
RequestStatus = reqInfo.RequestStatus
};
I hope I'm making sense here - I only want the requestapps based on the conditions, not all the request information that is those conditions. RequestApps is a part of the RequestInformation class.
Edit:
Piggybacking off of Roberts comments, I modified his code to look like this, but I am struggling with the last line - I need to be able to make sure that "AppDataChoiceDL" which is a member of RequestAppDataChoices (which is a member of RequestApps) is equal to groupName
var PullData = _context.RequestInformation.Include(x => x.RequestMinistry)
.Include(x => x.RequestApps)
.ThenInclude(x => x.RequestAppDataChoices)
.Where(x => x.RequestStatus != "Cancelled With Reason")
.Where(x => x.RequestApps.SelectMany(app => app.RequestAppDataChoices)
.Where(a => a.AppDataChoiceDl.Contains(groupName))
.Where(b => b.RequestApps.AppProvisioningCompleteTime != null)
.Where(c => c.RequestApps.AppTeamCompleteTime == null)
.Any(n => !n.RequestApps.AppStatus.Contains("Rejected"))).Select(reqInfo => new RequestInformation
{
ProvisioningCompleteTime = reqInfo.ProvisioningCompleteTime,
RequestMinistry = reqInfo.RequestMinistry,
UserFirstName = reqInfo.UserFirstName,
UserLastName = reqInfo.UserLastName,
SubmitterFirstName = reqInfo.SubmitterFirstName,
SubmitterLastName = reqInfo.SubmitterLastName,
RequestStatus = reqInfo.RequestStatus,
RequestApps = reqInfo.RequestApps
.Where(a => a.AppProvisioningCompleteTime != null)
.Where(b => b.AppTeamCompleteTime == null)
.Where(x => !x.AppStatus.Contains("Rejected"))
.Where(b => b.RequestAppDataChoices.Where(a => a.AppDataChoiceDl == groupName))
});
This throws an error not being able to convert IENUmerable to bool.. maybe I'm selecting my RequestAppDataChoices wrong?
This assumes you have a RequestInformationDto class that closely resembles your RequestInformation class:
var PullData = _context.RequestInformation.Include(x => x.RequestMinistry)
.Include(x => x.RequestApps)
.ThenInclude(x => x.RequestAppDataChoices)
.Where(x => x.RequestStatus != "Cancelled With Reason")
.Where(x => x.RequestApps.SelectMany(app => app.RequestAppDataChoices)
.Where(x => x.AppDataChoiceDl.Contains(groupName))
.Where(x => x.RequestApps.AppProvisioningCompleteTime != null)
.Where(x => x.RequestApps.AppTeamCompleteTime == null)
.Where(x => !x.RequestApps.AppStatus.Contains("Rejected")).Any())
.Select(reqInfo => new RequestInformationDto {
ProvisioningCompleteTime = reqInfo.ProvisioningCompleteTime,
RequestMinistry = reqInfo.RequestMinistry,
RequestApps = reqInfo.RequestApps
.Where(app => app.AppProvisioningCompleteTime != null)
.Where(app => app.AppTeamCompleteTime == null)
.Where(app => !app.AppStatus.Contains("Rejected")).Any())
.ToList()
UserFirstName = reqInfo.UserFirstName,
UserLastName = reqInfo.UserLastName,
SubmitterFirstName = reqInfo.SubmitterFirstName,
SubmitterLastName = reqInfo.SubmitterLastName,
RequestStatus = reqInfo.RequestStatus
});
I just noticed this part of your query, which should probably be reworked (or removed) as well:
.Where(x => x.RequestApps.SelectMany(app => app.RequestAppDataChoices)
.Where(x => x.AppDataChoiceDl.Contains(groupName))
.Where(x => x.RequestApps.AppProvisioningCompleteTime != null)
.Where(x => x.RequestApps.AppTeamCompleteTime == null)
.Where(x => !x.RequestApps.AppStatus.Contains("Rejected")).Any())
With Robert McKee's help, I was able to come up with this, that does work:
var PullData = _context.RequestInformation.Include(x => x.RequestMinistry)
.Include(x => x.RequestApps)
.ThenInclude(x => x.RequestAppDataChoices)
.Where(x => x.RequestStatus != "Cancelled With Reason")
.Where(x => x.RequestApps.SelectMany(app => app.RequestAppDataChoices)
.Where(a => a.AppDataChoiceDl.Contains(groupName))
.Where(b => b.RequestApps.AppProvisioningCompleteTime != null)
.Where(c => c.RequestApps.AppTeamCompleteTime == null)
.Any(n => !n.RequestApps.AppStatus.Contains("Rejected"))).Select(reqInfo => new RequestInformation
{
ProvisioningCompleteTime = reqInfo.ProvisioningCompleteTime,
RequestMinistry = reqInfo.RequestMinistry,
UserFirstName = reqInfo.UserFirstName,
UserLastName = reqInfo.UserLastName,
SubmitterFirstName = reqInfo.SubmitterFirstName,
SubmitterLastName = reqInfo.SubmitterLastName,
RequestStatus = reqInfo.RequestStatus,
RequestApps = reqInfo.RequestApps
.Where(a => a.AppProvisioningCompleteTime != null)
.Where(b => b.AppTeamCompleteTime == null)
.Where(x => !x.AppStatus.Contains("Rejected"))
.Where(b => b.RequestAppDataChoices.Any(a => a.AppDataChoiceDl == groupName)).ToList()
});

Dynamic Bool Query for NEST (ElasticSearch)

Good day:
I'm trying to achieve a dynamic Bool Query. Example...
QueryContainer addressQuery = null;
QueryContainer typeQuery = null;
BoolQueryDescriptor <Facility> boolQuery = new BoolQueryDescriptor<Facility>();
QueryContainerDescriptor<Facility> sh = new QueryContainerDescriptor<Facility>();
SearchDescriptor<Facility> mainSh = new SearchDescriptor<Facility>();
if (search.searchTerm != null)
{
addressQuery = sh.Term(f => f.Address, search.searchTerm) ||
sh.Match(m => m.Field(f => f.Address).Query(search.searchTerm) ) ||
sh.Term(f => f.ZipCode, search.searchTerm) ||
sh.Match(m => m.Field(f => f.State).Query(search.searchTerm));
boolQuery = boolQuery.Should(b => addressQuery);
}
if (search.type != null) {
typeQuery = sh.Term(f => f.Types.First(), search.type);
boolQuery = boolQuery.Must(b => typeQuery && addressQuery);
}
if (boolQuery != null)
{
mainSh = mainSh.Query(q => q.Bool(b => boolQuery));
request = await this._elasticClient.SearchAsync<Facility>(s => mainSh.Size(search.size));
}
This query is turning into a OR between AddressQuery and TypeQuery however, I'd like to achieve an And condition between both query. Effectively making the query dynamic. Is this possible? Example: dynamic addressQuery && typeQuery.
Thanks.
Fire it out..you can && or || query containers...sorter like:
queryContainer1=queryContainer1 && queryContainer2
Then .bool(b => b(queryContainer1)).

Linq to sql - nested select with groupby

I have the following SQL query:
SELECT * FROM [dbo].[Bil_Audit_BillingParameter] WHERE ([Status4Eyes]!='APPROVED' OR [Status4Eyes] IS NULL )AND
[LastComment] != '' AND
(Service='EUR' OR Service='S1') AND
[AudId] IN (SELECT MAX([AudId])
FROM [Bil_Audit_BillingParameter]
GROUP BY ID) UNION SELECT * FROM
[dbo].Bil_Audit_BillingParameter] WHERE ([Status4Eyes]!='APPROVED' OR [Status4Eyes] IS NULL) AND
[LastComment] != '' AND
(Service='EUR' OR Service='S1') AND
[AudId] IN (SELECT MIN([AudId])
FROM [Bil_Audit_BillingParameter]
GROUP BY ID)
How it is converting to linq? I tried the following , but ends up with error.
public IQueryable<ParameterUpdates> Get(ODataQueryOptions op)
{
var audIdMax = db.ParameterUpdates.GroupBy(x => x.ID).Select(v => v.Max(x => x.AudId));
var audIdMin = db.ParameterUpdates.GroupBy(x => x.ID).Select(a => a.Min(x => x.AudId));
var results1 = db.ParameterUpdates.Where(p => (!p.Status4Eyes.Contains("Approved") || string.IsNullOrEmpty(p.Status4Eyes)) &&
!p.LastComment.Contains("NULL") &&
(p.Service.Contains("EUR") || p.Service.Contains("S1")) &&
p.AudId.Equals(audIdMax));
var results2 = db.ParameterUpdates.Where(p => (!p.Status4Eyes.Contains("Approved") || string.IsNullOrEmpty(p.Status4Eyes)) &&
!p.LastComment.Contains("NULL") &&
(p.Service.Contains("EUR") || p.Service.Contains("S1")) &&
p.AudId.Equals(audIdMin));
var results = results1.Union(results2);
return results.AsQueryable();
}
Could anyone please help.
You can try this, first group by id create the filter output. Then inner join the filter with max or min audit id with the actual table and find the result.
var filter = ParameterUpdate.Where(p => (p.status == "Approved" || p.status == null)
&& p.lastComment != ""
&&(p.service=="EUR" || p.service=="S1")).GroupBy(p => p.id);
var result = (from p in ParameterUpdate
from f in filter
where p.auditId == f.Min(m => m.auditId) ||
p.auditId == f.Max(m => m.auditId)
select p);
public IQueryable<ParameterUpdates> Get()
{
var groupMax = db.ParameterUpdates
.GroupBy(u => u.ID)
.Select(grp => grp.Max(x => x.AudId));
var groupMin = db.ParameterUpdates
.GroupBy(u => u.ID)
.Select(grp => grp.Min(x => x.AudId));
var results = (db.ParameterUpdates.
Where(r => (r.Status4Eyes != "APPROVED" || r.Status4Eyes == null) &&
(r.LastComment != null) &&
(r.Service == "EUR" || r.Service == "S1") &&
(groupMax.Contains(r.AudId) || groupMin.Contains(r.AudId))
)).ToList();
return results.AsQueryable();

Linq join and group by

I am trying to write the following PLSQL query in linq, but am coming a little unstuck on the group by:
select
sub.EmpID,
Min(sub.Stage1) Stage1,
Min(sub.Stage2) Stage2,
Min(sub.Stage3) Stage3,
Min(sub.Prob1) Prob1,
Min(sub.Prob2) Prob2
from
(select
det.det_numbera EmpID,
case when apr.apr_performa = '1'
then max(apr.apr_datec)
else null
end Stage1,
case when apr.apr_performa = '2'
then max(apr.apr_datec)
else null
end Stage2,
case when apr.apr_performa = '3'
then max(apr.apr_datec)
else null
end Stage3,
case when apr.apr_performa = '5'
then max(apr.apr_datec)
else null
end Prob1,
case when apr.apr_performa = '6'
then max(apr.apr_datec)
else null
end Prob2
from emdet det
left outer join emapr apr
on det.det_numbera = apr.det_numbera
group by det.det_numbera, apr.apr_performa) sub
group by sub.Empid
I have managed to partially do the sub query but came unstuck on the grouping before I could get the outer query working:
public List<ComplianceDetails> MyComplianceDetails(List<JobDetail> staff, List<Compliance> compliance)
{
List<ComplianceDetails> compdet =
(from s in staff
join c in compliance on s.EmpID equals c.EmpId into staffcomp
from sc in staffcomp.DefaultIfEmpty()
group s by new { s.EmpID, sc.Stage } into grp
select new ComplianceDetails(
s.EmpID,
s.Position,
s.Department,
s.Division,
s.Contract,
s.ContService,
s.Probation,
s.Sessional,
s.Teaching,
sc.Stage == "1" ? staffcomp.Max(a => a.LastDate) : (DateTime?)null,
sc.Stage == "2" ? staffcomp.Max(a => a.LastDate) : (DateTime?)null,
sc.Stage == "3" ? staffcomp.Max(a => a.LastDate) : (DateTime?)null,
sc.Stage == "5" ? staffcomp.Max(a => a.LastDate) : (DateTime?)null,
sc.Stage == "6" ? staffcomp.Max(a => a.LastDate) : (DateTime?)null
)
).ToList();
return compdet;
}
EDIT//
Thanks for the help, you guided me very close to the solution this seems to work as expected:
public List<ComplianceDetails> MyComplianceDetails(List<JobDetail> staff, List<Compliance> compliance)
{
string[] tQuals = new string[] { "21", "22", "23", "24" };
var compdet =
(from det in staff
join apr in compliance on det.EmpID equals apr.EmpId
into JoinedList
from apr in JoinedList.DefaultIfEmpty()
group new { det, apr } by
new
{
det.EmpID,
Stage = apr == null ? "" : apr.Stage
} into GroupedList
select GroupedList.Select(u => new
{
EmpID = u.det.EmpID,
FullName = u.det.FullName,
Position = u.det.Position,
Department = u.det.Department,
Division = u.det.Division,
Contract = u.det.Contract,
ContService = u.det.ContService,
Probation = u.det.Probation,
Sessional = u.det.Sessional,
Teaching = u.det.Teaching,
Stage1 = u.apr == null ? null : (u.apr.Stage == "1" ? GroupedList.Max(t => t.apr.LastDate) : (DateTime?)null),
Stage2 = u.apr == null ? null : (u.apr.Stage == "2" ? GroupedList.Max(t => t.apr.LastDate) : (DateTime?)null),
Stage3 = u.apr == null ? null : (u.apr.Stage == "3" ? GroupedList.Max(t => t.apr.LastDate) : (DateTime?)null),
Prob1 = u.apr == null ? null : (u.apr.Stage == "5" ? GroupedList.Max(t => t.apr.LastDate) : (DateTime?)null),
Prob2 = u.apr == null ? null : (u.apr.Stage == "6" ? GroupedList.Max(t => t.apr.LastDate) : (DateTime?)null),
EduType = u.apr == null ? string.Empty : (tQuals.Contains(u.apr.Stage) ? u.apr.StageDesc : string.Empty),
EduDate = u.apr == null ? null : (tQuals.Contains(u.apr.Stage) ? GroupedList.Max(t => t.apr.LastDate) : (DateTime?)null)
})
)
.SelectMany(u => u)
.GroupBy(u => u.EmpID)
.Select(u => new ComplianceDetails
(
u.Key,
u.First().FullName,
u.First().Position,
u.First().Department,
u.First().Division,
u.First().Contract,
u.First().ContService,
u.First().Probation,
u.First().Sessional,
u.First().Teaching,
u.Where(t => t.Stage1 == u.Max(T => T.Stage1)).Select(g => g.Stage1).FirstOrDefault(),
u.Where(t => t.Stage2 == u.Max(T => T.Stage2)).Select(g => g.Stage2).FirstOrDefault(),
u.Where(t => t.Stage3 == u.Max(T => T.Stage3)).Select(g => g.Stage3).FirstOrDefault(),
u.Where(t => t.Prob1 == u.Max(T => T.Prob1)).Select(g => g.Prob1).FirstOrDefault(),
u.Where(t => t.Prob2 == u.Max(T => T.Prob2)).Select(g => g.Prob2).FirstOrDefault(),
u.Where(t => t.EduDate == u.Max(T => T.EduDate)).Select(g => g.EduType).FirstOrDefault(),
u.Where(t => t.EduDate == u.Max(T => T.EduDate)).Select(g => g.EduDate).FirstOrDefault()
))
.ToList();
return compdet;
}
this is equivalent linq of your tsql, check this:
var query = (from det in emdet
join apr in emapr on det.det_numbera equals apr.det_numbera
into JoinedList
from apr in JoinedList.DefaultIfEmpty()
group new { det, apr } by
new
{
det.det_numbera,
apr_performa = apr == null ? "" : apr.apr.apr_performa
} into GroupedList
select GroupedList.Select(u => new
{
EmpID = u.det.det_numbera,
Stage1 = u.apr == null ? null : (u.apr.apr_performa == "1" ? GroupedList.Max(t => t.apr_datec) : null),
Stage2 = u.apr == null ? null : (u.apr.apr_performa == "2" ? GroupedList.Max(t => t.apr_datec) : null),
Stage3 = u.apr == null ? null : (u.apr.apr_performa == "3" ? GroupedList.Max(t => t.apr_datec) : null),
Prob1 = u.apr == null ? null : (u.apr.apr_performa == "5" ? GroupedList.Max(t => t.apr_datec) : null),
Prob2 = u.apr == null ? null : (u.apr.apr_performa == "6" ? GroupedList.Max(t => t.apr_datec) : null)
})
)
.SelectMany(u => u)
.GroupBy(u => u.EmpID)
.Select(u => new
{
EmpID = u.Key,
Stage1 = u.Where(t => t.Stage1 != null).DefaultIfEmpty().Min(t => t.Stage1),
Stage2 = u.Where(t => t.Stage2 != null).DefaultIfEmpty().Min(t => t.Stage2),
Stage3 = u.Where(t => t.Stage3 != null).DefaultIfEmpty().Min(t => t.Stage3),
Prob1 = u.Where(t => t.Prob1 != null).DefaultIfEmpty().Min(t => t.Prob1),
Prob2 = u.Where(t => t.Prob2 != null).DefaultIfEmpty().Min(t => t.Prob2)
})
.ToList();

How to get conditional Include children entity and his related entity

The following code work for me:
var query0 = DB.Plan
.Include("UserCreate")
.Include("UserUpdate")
.Include("PlanTemplate")
.Select(p => new
{
plan = p,
planItems = p.PlanItems.Where(pi => pi.IsCommited == true && pi.IsLocked == false)
});
var query2 = query0.AsEnumerable().Where(m => m.planItems.Count() > 0).Select(m => m.plan);
But the planItems related to another entities that I wanted,the following code do not work for me:
var query0 = DB.WorkEffortPlan
.Include("UserCreate")
.Include("UserUpdate")
.Include("PlanTemplate")
.Select(p => new
{
plan=p,
planItems = DB.PlanItem
.Include("UserResponsiblePerson")
.Include("TemplateItem")
.Include("ItemState")
.Where(pi => pi.PlanID == p.PlanID && pi.IsCommited == true && pi.IsLocked == false)
});
var query2 = query0.AsEnumerable().Where(m => m.planItems.Count() > 0).Select(m => m.plan);
The vs compiler is run OK,but when exec this code,I get the NullReferenceException in query0.
Is there any linq solution to get filtering children entity and his related entity?

Resources