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

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

Related

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 Join queries

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.

Reactive ToProperty not setting property

I have the property Sessions in my vm
private ObservableAsPropertyHelper<IEnumerable<SessionViewModel>> _Sessions;
public IEnumerable<SessionViewModel> Sessions
{
get { return _Sessions.Value; }
}
I am trying to set this in the constructor like so
this.WhenAny(x => x.LocationsViewModel.CurrentLocation, x => x.Date, (location, date) => location.Value)
.Where(x => x != null)
.Select(x => FilterSessions(x.Id, Date))
.ToProperty(this, x => x.Sessions);
FilterSessions looks like so
private IEnumerable<SessionViewModel> FilterSessions(Guid locationId, DateTime date)
{
return _allSessions
.Where(s => s.SessionLocationId == locationId && s.StartTime.Date == date.Date)
.Select(s => new SessionViewModel(s));
}
It returns 10 SessionViewModel's but _Sessions is never set.
What platform is this? Certain platforms do not allow setting private fields via reflection. Instead, you can just use the return value of ToProperty:
_Sessions = this.WhenAny(x => x.LocationsViewModel.CurrentLocation, x => x.Date, (location, date) => location.Value)
.Where(x => x != null)
.Select(x => FilterSessions(x.Id, Date))
.ToProperty(this, x => x.Sessions);
Or better, in RxUI 5.x:
this.WhenAny(x => x.LocationsViewModel.CurrentLocation, x => x.Date, (location, date) => location.Value)
.Where(x => x != null)
.Select(x => FilterSessions(x.Id, Date))
.ToProperty(this, x => x.Sessions, out _Sessions);
I worked around this by settings the property in the subscribe method like so:
this.WhenAny(x => x.LocationsViewModel.CurrentLocation, x => x.Date, (location, date) => location.Value)
.Where(x => x != null)
.Select(x => FilterSessions(x.Id, Date))
.Subscribe(x => Sessions = x);

How to use whereif in LINQ

Hi can someone help me how best we can use whereif in LINQ
IQueryable<Employee> empQuery;
if (empId == "")
{
empQuery = dbContext.Emps
.Include(x => x.Name)
.Include(x => x.Code)
.Where(x => x.Id == empId);
}
else
{
empQuery = dbContext.Emps
.Include(x => x.Name)
.Include(x => x.Code);
}
I think we can make this query very simple by using whereif right? Can someone help me how to make this query simple by using whereif? Instead of check if (empid == "") ?
Is it possible?
I assume "whereif" is supposed to be this extension method. You can't use that, because it operates on an IEnumerable<T> and not on a IQueryable<T>. The result would be that you would request your complete employees table from the database and perform the filtering in memory in your application. That's not what you want. You can, however, use the conditional operator to achieve this:
var empQuery = dbContext.Emps
.Include(x => x.Name)
.Include(x => x.Code)
.Where(x => empId == "" ? true : x.Id == empId);
Please note that this assumes that you actually meant if(empId != "") in your sample code. If you didn't mean this, switch the second and third operand around:
.Where(x => empId == "" ? x.Id == empId : true);
Having said this, you certainly can create the same extension method for IQueryable<T>. It looks nearly the same, just has IEnumerable<T> replaced with IQueryable<T> and the predicate changed to an expression:
public static IQueryable<TSource> WhereIf<TSource>(
this IQueryable<TSource> source,
bool condition,
Expression<Func<TSource, bool>> predicate)
{
if (condition)
return source.Where(predicate);
else
return source;
}
I believe you want filtering by empId if it is not empty. Simple OR operator will do the job:
IQueryable<Employee> empQuery = dbContext.Emps
.Include(x => x.Name)
.Include(x => x.Code)
.Where(x => empId == "" || x.Id == empId);
Also you can build query dynamically:
IQueryable<Employee> empQuery = dbContext.Emps
.Include(x => x.Name)
.Include(x => x.Code);
if (empId != "")
empQuery = empQuery.Where(x => x.Id == empId);
.Where(x => x.Id == empId);
Doesn't make sense if the value is '""' - what do you expect it to return?
var query = (from items in dbContext.Emps
where items.Id == empId
select new {
Name = items.Name,
Code = items.Code
}).ToList();

Linq - How to exclude items from autocomplete array

I have the following code that gives me a an array in an autocomplete extender:
return autocomplete.tblAutoCompletes
.Where(p => p.MemberId == memberid && p.LocationId == locationid && p.ACItem.Contains(prefixText))
.OrderBy(p => p.ACItem)
.Select(p => p.ACItem)
.Take(count)
.ToArray();
However, I may need to programmatically exclude certain items from the array.
How would I do that? So for example, ACItem list = Product1, Product2, Product3.
How would I amend the code so that Product2 is excluded?
autocomplete.tblAutoCompletes
.Where(p => p.MemberId == memberid && p.LocationId == locationid && p.ACItem.Contains(prefixText))
.OrderBy(p => p.ACItem)
.Select(p => p.ACItem)
.Take(count)
.Where(p => p != Product1)
.Select(p => p)
.ToArray();

Resources