I have those statements who checks if I have all the answers in a Grid. Each row is identified by a ContextYID.
I would like to know if i can combine those LinQ query and convert it directly to a True/False Statement.
int nbRow = Answers.Where(a => a.FieldId == result.Id && a.FieldYId == fieldYAxi.Id)
.Select(a => a.ContextYId)
.Distinct()
.Count();
int nbAnswer = Answers.Count(a =>
a.FieldId == result.Id &&
a.FieldXId == fieldXAxi.Id &&
a.FieldYId == fieldYAxi.Id);
if (nbAnswer != nbRow)
return false;
else
return true;
I think this is an improvement, because the FieldId and FieldYID only need to be compared once, and I simplified your return statements into one line.
var matchingAnswers = Answers.Where(a => a.FieldId == result.Id
&& a.FieldYId == fieldYAxi.Id).ToList();
int nbRow = matchingAnswers
.Select(a => a.ContextYId)
.Distinct()
.Count();
int nbAnswer = matchingAnswers.Count(a => a.FieldXId == fieldXAxi.Id);
return nbAnswer == nbRow;
If you like, you can shorten this by merging the last few lines:
var matchingAnswers = Answers.Where(a => a.FieldId == result.Id
&& a.FieldYId == fieldYAxi.Id).ToList();
return matchingAnswers.Count(a => a.FieldXId == fieldXAxi.Id) ==
matchingAnswers.Select(a => a.ContextYId).Distinct().Count();
Wouldn't equals work?
return Answers.Where(a => a.FieldId == result.Id && a.FieldYId == fieldYAxi.Id)
.Select(a => a.ContextYId)
.Distinct()
.Count()
.Equals(Answers.Count(a =>
a.FieldId == result.Id &&
a.FieldXId == fieldXAxi.Id &&
a.FieldYId == fieldYAxi.Id));
I think this should work. Is there a particular reason you want to do this?
return Answers.Where(a => a.FieldId == result.Id && a.FieldYId == fieldYAxi.Id)
.Select(a => a.ContextYId)
.Distinct()
.Count()
== Answers.Count(a => a.FieldId == result.Id
&& a.FieldXId == fieldXAxi.Id
&& a.FieldYId == fieldYAxi.Id)
I think this is functionally equivalent to what are doing (but I do wonder what you're doing for the duplicate ContextYIds that satisfy nbAnswer multiple times):
var distinctContextYIds = new HashSet<int>();
return 0 == Answers.Where(a => a.FieldId == result.Id && a.FieldYId == fieldYAxi.Id)
.Aggregate(0, (tally, answer) =>
{
if (distinctContextYIds.Add(answer.ContextYId))
tally += 1;
if (answer.FieldXId == fieldXAxi.Id)
tally -= 1;
return tally;
});
Related
I created where conditions with linq lambda expression for reporting. My conditions are running very slowly or it is throwing error.
Error Detail: Evoluation timed out.
How can i find correct query?
My codes:
var query = Worker.Members
.Where(u => string.IsNullOrEmpty(model.TcNumber) || u.TcNumber.Contains(model.TcNumber))
.Where(u => string.IsNullOrEmpty(model.FullName) || u.FullName.Contains(model.FullName))
.Where(u => model.BirthYear == null || u.BirthDate.Year >= model.BirthYear)
.Where(u => model.BirthYearLevel == null || u.BirthDate.Year <= model.BirthYearLevel)
.Where(u => model.BirthYearLevel == null || u.BirthDate.Year <= model.BirthYearLevel)
.Where(u => model.GenderId == null || u.GenderId == model.GenderId)
.Where(u => model.DistrictCode == null || u.Contacts.Any(c => c.DistrictCode == model.DistrictCode && c.IsActive))
.Where(u => model.StreetCode == null || u.Contacts.Any(c => c.StreetCode == model.StreetCode && c.IsActive))
.Where(u => model.ExteriorDoor == null || u.Contacts.Any(c => c.ExteriorDoor == model.ExteriorDoor && c.IsActive))
.Where(u => model.InteriorDoor == null || u.Contacts.Any(c => c.InteriorDoor == model.InteriorDoor && c.IsActive))
.Where(u => model.DisabledGroupId == null || u.Disableds.Any(d => d.ReportDisabledGroups.Any(c => c.DisabledGroupId == model.DisabledGroupId)))
.Where(u => model.ContributionTypeId == null || u.Demands.Any(d => d.ContributionTypeId == model.ContributionTypeId && !d.IsDeleted))
.Where(u => model.DemandStatusId == null || u.Demands.Any(d => d.DemandStatusId == model.DemandStatusId && !d.IsDeleted))
.Where(u => model.DemandDateStart == null || u.Demands.Any(d => d.DemandDate >= model.DemandDateStart && !d.IsDeleted))
.Where(u => model.DemandDateEnd == null || u.Demands.Any(d => d.DemandDate <= model.DemandDateEnd && !d.IsDeleted))
.Where(u => u.IsTcCitizen == model.IsForeign)
.Where(u => u.IsDisabled == model.IsDisabled)
.Where(u => u.IsAlive == model.IsAlive);
The correct pattern (assuming Worker.Members is an IQueryable, not an IEnumerable) here is to conditionally add the criteria, like this:
var query = Worker.Members;
if (!string.IsNullOrEmpty(model.TcNumber))
query = query.Where(u => u.TcNumber.Contains(model.TcNumber));
if (!string.IsNullOrEmpty(model.FullName)
query = query.Where(u => u.FullName.Contains(model.FullName));
if (!model.BirthYear == null)
query = query.Where(u => u.BirthDate.Year >= model.BirthYear);
. . .
Did you check this?
Here detailed descriptions are given.
My requirement is to make boolean value (IsPC=true) only if I found any value with IsCurrent = true from the list and second condition is to filter the list with G or W codes and third condition is to check the PCBNumber length ==15 with only one from the list.
How short can i able to reduce the below query using LINQ method syntax
below is my query
var CurrentQ= p.List.Where(x => x.IsConCurrent== true);
if (CurrentQ.Count() > 0)
{
var NCurrentQwithWorQ = p.List.Where(x => x.Codes == Codes.W|| x.Codes== Codes.Q).Count();
if (NCurrentQwithWorQ != null)
{
var PCBNumber = p.List.Where(x => x.PCBNumber .Length == 15).Count();
if (PCBNumber == 1)
{
isPC = true;
}
}
}
You can use all conditions in same query like below,
var PCBNumber= p.List.Where(x => x.IsConCurrent== true && (x.Codes == Codes.W|| x.Codes== Codes.Q) && x.PCBNumber.Length == 15);
if (PCBNumber !=null && PCBNumber.Count() == 1)
{
isPC = true;
}
I'm not trying to debug what you wrote, but isn't this really what you're looking for--that is, daisy-chaining your Where conditions?
var isPC = p.List.Where(x => x.IsConCurrent == true).Where(x => x.Codes == Codes.W || x.Codes == Codes.Q).Where(x => x.PCBNumber.Length == 15).Count() == 1;
Both solutions suggested above are correct.
p.List.Where(x => x.IsConCurrent== true && (x.Codes == Codes.W|| x.Codes== Codes.Q) && x.PCBNumber.Length == 15);
p.List.Where(x => x.IsConCurrent == true).Where(x => x.Codes == Codes.W || x.Codes == Codes.Q).Where(x => x.PCBNumber.Length == 15).Count()
Actually they are performed in the same way. The Where function does not force immediate iteration through the data source. Only when you execute the Count function, LINQ will process row by row and execute criterion by criterion to find out which values should be calculated.
I can only suggest you add the Take(2) operator after the where clause. In this case LINQ will stop after finding the first two rows that matches provided criterion and other rows will not be processed.
p.List.Where(x => x.IsConCurrent == true)
.Where(x => x.Codes == Codes.W || x.Codes == Codes.Q)
.Where(x => x.PCBNumber.Length == 15)
.Take(2).Count()
I have the following code:
decimal? sumFreightAmount = (db.Trips
.Where(p => p.DateTime.Month == i && p.DateTime.Year == DateTime.Now.Year)
.Sum(p => p.FreightAmount));
if (sumFreightAmount.HasValue)
{
// my actions
}
else
{
sumFreightAmount = 0;
}
I can write it the following way:
decimal sumFreightAmount = (
db.Trips
.Where(p => p.DateTime.Month == i && p.DateTime.Year == DateTime.Now.Year)
.Sum(p => p.FreightAmount) != null)
?
(db.Trips
.Where(p => p.DateTime.Month == i && p.DateTime.Year == DateTime.Now.Year)
.Sum(p => p.FreightAmount)) : 0;
but in this place I call linq extension twice (and have a long record). I have read, that I can write more shorter it in the latest version of C#, like
decimal sumFreightAmount = (db.Trips.Where(p => p.DateTime.Month == i && p.DateTime.Year == DateTime.Now.Year).Sum(p => p.FreightAmount)?.0;
but can't find it. What is the shortest record?
The best way is using GetValueOrDefault
decimal sumFreightAmount = db.Trips
.Where(p => p.DateTime.Month == i && p.DateTime.Year == DateTime.Now.Year)
.Sum(p => p.FreightAmount)
.GetValueOrDefault();
EDIT: As #IvanStoev pointed out, you can also use the null coalescing operator in this case, which is a tad bit shorter:
decimal sumFreightAmount = db.Trips
.Where(p => p.DateTime.Month == i && p.DateTime.Year == DateTime.Now.Year)
.Sum(p => p.FreightAmount) ?? 0;
This is my method:
public IEnumerable<Web_Vendor> GetSaleBrands()
{
using (var _db = new LuxedecorContext())
{
IQueryable<Web_Vendor> web_vendors = _db.Web_Vendor.
Where(x =>
(_db.Web_Promotion.Where(z => z.VendorID != string.Empty
&& z.Static == true && z.Percent != 0 &&
(x.WebPromotion.Expires >= DateTime.Now || x.WebPromotion.Expires == null))
.Select(r => r.VendorID).Contains(x.VendorID))
||
(_db.NavItems.Where(y => x.WebPromotion.VendorID == y.SC1
&& !(y.Promotion == "" || y.Promotion == null)
&& (y.PromotionStart <= DateTime.Now) && (y.PromotionEnd >= DateTime.Now || y.PromotionEnd == null))
.Select(g => g.SC1).Contains(x.WebPromotion.VendorID)))
.Where(x => x.Active == true).OrderBy(x => x.NameExtra)
.ThenBy(x => x.Sequence);
var a = web_vendors.ToList(); // 16 values
var b = web_vendors.Include(x => x.WebPromotion).ToList(); // 13 values
}
throw new NotImplementedException();
}
I need to Include nullable values to my collection of Web_Vendors. I know, it's famous question, but I need to return collection of Web_Vendors instead of collection of dynamic types. Is it possible?
I am trying to get the result based upon the values of variables temp_DestinationGroupName, temp_CountryName and temp_RateTypeId.
If any of these variables are null or 0, it should not be included in where clause and rest statements should work and bring the result. I am getting zero rows using this query. Kindly suggest me something with these conditions in where clause. i tried following solutions on stackoverflow but still not getting the desired result.
var Rows = _CustomerRatesList.Where(w => (w.Id != rates.Id)
&& (w.DestinationGroupName == temp_DestinationGroupName || temp_DestinationGroupName!= null)
&& (w.CountryName == temp_CountryName || temp_CountryName!=null)
&& (w.RateTypeId == temp_RateTypeId || temp_RateTypeId !=0));
(w.DestinationGroupName == temp_DestinationGroupName || temp_DestinationGroupName!= null)
Your condition here will return true as long as your input variable temp_DestinationGroupName is not null. I don't think that's what you had in mind.
You can split in many Where to make your request more readable :
var Rows = _CustomerRatesList.Where(w => w.Id != rates.Id)
.Where(w => w.DestinationGroupName != temp_DestinationGroupName || temp_DestinationGroupName != null)
.Where(w => w.CountryName != temp_CountryName || temp_CountryName != null)
.Where(w => w.RateTypeId != temp_RateTypeId || temp_RateTypeId !=0);
Notice that you must use != in first conditioon of all Where, so you'll get all data except when it's null. In your logic, may be the conditions will be == :
var Rows = _CustomerRatesList.Where(w => w.Id != rates.Id)
.Where(w => w.DestinationGroupName == temp_DestinationGroupName || temp_DestinationGroupName == null)
.Where(w => w.CountryName == temp_CountryName || temp_CountryName == null)
.Where(w => w.RateTypeId == temp_RateTypeId || temp_RateTypeId ==0);
Each Where result is an IEnumerable, Rows will be a IEnumerable. If you want a List, just add .ToList()
I got the solution to this problem, now i am getting filtered result.
Thank you all for your time :)
var otherRows = _CustomerRatesList.Where(w => w.Id != rates.Id)
.Where(w => w.DestinationGroupName == temp_DestinationGroupName || temp_DestinationGroupName == null)
.Where(w => w.CountryName == temp_CountryName || temp_CountryName == null)
.Where(w => w.RateTypeId == temp_RateTypeId || temp_RateTypeId == 0);