Using Multiple Conditions with Count - LINQ - c#

All,
I cannot seem to figure this out. I looked here and tried some different lambda expressions but to no avail. I am trying to do this for my condition:
(DateOrganized >= startDate.Date && DateOrganized <= endDate.Date)
This is all I have that will compile. How can I add another condition like above? Thanks
r.Count(x => x.DateOrganized <= endDate.Date);
This does not compile
r.Count(x => x.DateOrganized >= startDate.Date && x => x.DateOrganized <= endDate.Date);

Try
r.Count(x => (x.DateOrganized >= startDate.Date) &&
(x.DateOrganized <= endDate.Date));

Related

EF Core declaring multiple variables on complex Where Clause

I have this LINQ Where clause that is declaring 2 variables on the SQL query
var parkingLotPrice =
_context.ParkingLotPrice
.Where(x => currentDate >= x.EffectiveDate && (currentDate <= x.ExpiryDate || x.ExpiryDate == null))
.ToQueryString();
It generates this SQL Query:
DECLARE #__currentDate_0 datetime2 = '2021-07-21T17:48:29.1106534-06:00';
DECLARE #__currentDate_1 datetime2 = '2021-07-21T17:48:29.1106534-06:00';
SELECT [p].[ParkingLotId],
[p].[PriceScheduleId],
[p].[EffectiveDate],
[p].[ExpiryDate]
FROM [ParkingLotPrice] AS [p]
WHERE (#__currentDate_0 >= [p].[EffectiveDate]) AND ((#__currentDate_1 <= [p].[ExpiryDate]) OR [p].[ExpiryDate] IS NULL)
Note: the declarations contains the same value.
The problem is the (currentDate <= x.ExpiryDate || x.ExpiryDate == null).
If I remove the null evaluation, it only declares 1 variable.
DECLARE #__currentDate_0 datetime2 = '2021-07-21T17:32:31.3980763-06:00';
SELECT [p].[ParkingLotId],
[p].[PriceScheduleId],
[p].[EffectiveDate],
[p].[ExpiryDate]
FROM [ParkingLotPrice] AS [p]
WHERE (#__currentDate_0 >= [p].[EffectiveDate]) AND (#__currentDate_0 <= [p].[ExpiryDate])
Is there a way of keeping the Where evaluation, but only declare 1 variable?
And what is wrong with it? Does it return a wrong result? I created hundreds queries with null and without and they always returned the right result.
I can see the real problem in your query. The way you compare dates. It will compare times too. In some cases it will return a wrong result. I highly recommend you to compare only dates
var parkingLotPrice = _context.ParkingLotPrice
.Where(x => EF.Functions.DateDiffDay(x.EffectiveDate,currentDate) >=0
&& (x.ExpiryDate == null || EF.Functions.DateDiffDay(currentDate,x.ExpiryDate)>=0 )).ToList();
or if you need some time try this
var parkingLotPrice = _context.ParkingLotPrice
.Where(x => EF.Functions.DateDiffMinute(x.EffectiveDate,currentDate) >=0
&& (x.ExpiryDate == null || EF.Functions.DateDiffMinute(currentDate,x.ExpiryDate)>=0 )).ToList();

C# / LINQ - conditional LINQ query based on checkbox status

I'm trying to build a LINQ query that executes as values change, however I only want to bottom 4 statements relating to price and surface area to run on the condition that a certain checkbox on my Windows form is ticked. My code is below
var userSearchQuery =
from sale in saleData
where checkedCities.Contains(sale.City)
&& checkedBedrooms.Contains(sale.Bedrooms)
&& checkedBathrooms.Contains(sale.Bathrooms)
&& checkedHouseTypes.Contains(sale.HouseType)
&& minPrice <= sale.Price
&& maxPrice >= sale.Price
&& minSurfaceArea <= sale.SurfaceArea
&& maxSurfaceArea >= sale.SurfaceArea
select sale;
Can anyone help with the best way to do this please
What you could do is make the base query just as it is. So just remove last 4 conditions that you wish to dinamically add depending on some condition from UI. You will see that your query is of type IQueryable.
var userSearchQuery =
from sale in saleData
where checkedCities.Contains(sale.City)
&& checkedBedrooms.Contains(sale.Bedrooms)
&& checkedBathrooms.Contains(sale.Bathrooms)
&& checkedHouseTypes.Contains(sale.HouseType);
Do not select anything yet. Now add your condition depending on UI.
if(checkBox1.Checked)
userSearchQuery = userSearchQuery.Where(s => minPrice <= s.Price);
if(checkBox2.Checked)
userSearchQuery = userSearchQuery.Where(s => maxPrice => s.Price);
if(checkBox3.Checked)
userSearchQuery = userSearchQuery.Where(s => minSurfaceArea => s.SurfaceArea);
if(checkBox4.Checked)
userSearchQuery = userSearchQuery.Where(s => maxSurfaceArea => s.SurfaceArea);
Finally execute the query by calling ToList().
var results = userSearchQuery.Select(s => s).ToList();
You can stack the queries, so first create an IEnumerable for all cases and then add additional queries to previous IEnumerable only when your checkbox is checked.
var userSearchQuery = from sale in saleData
where checkedCities.Contains(sale.City)
&& checkedBedrooms.Contains(sale.Bedrooms)
&& checkedBathrooms.Contains(sale.Bathrooms)
&& checkedHouseTypes.Contains(sale.HouseType)
select sale;
if (checkbox.IsChecked)
{
userSearchQuery = from sale in userSearchQuery
where minPrice <= sale.Price
&& maxPrice >= sale.Price
&& minSurfaceArea <= sale.SurfaceArea
&& maxSurfaceArea >= sale.SurfaceArea
select sale;
}
You could use the fact that 'true' returns the result as follows:
var userSearchQuery =
from sale in saleData
where checkedCities.Contains(sale.City)
&& checkedBedrooms.Contains(sale.Bedrooms)
&& checkedBathrooms.Contains(sale.Bathrooms)
&& checkedHouseTypes.Contains(sale.HouseType)
&& (*some condition is checked*) ? (minPrice <= sale.Price && maxPrice >= sale.Price && minSurfaceArea <= sale.SurfaceArea && maxSurfaceArea >= sale.SurfaceArea) : true
select sale;
I have tested the syntax, but not the execution so let me know if it doesn't work as expected.
For reading reference about the '?' operator:
?: Operator (C# Reference)
EDITED:
As per apocalypse's comment, there is no need to check the condition multiple times.

Whats wrong in this Linq query

var MyCours = Db.COURS.Where(C => C.CLASSE_ID == ClassID
&& DateTime.Now>= C.START_DATE
&& DateTime.Now <= C.END_DATE)
.ToList();
Some change still dont work !
A likely problem is that the provider can't project DateTime.Compare into a SQL statement. There is potentially also a logical error in the direction of comparison (unless you really want enddate < now < startdate), and I would also suggest using .ToList() to materialize into a list:
var theTimeNow = DateTime.Now;
var MyCours = Db.COURS.Where(C => C.CLASSE_ID == ClassID
&& theTimeNow >= C.START_DATE
&& theTimeNow <= C.END_DATE)
.ToList();
Projecting DateTime.Now into a variable isolates the non-determinism of it, i.e. to ensure that both comparisons are against the same time.

DateDiff alternative in Linq

I'm trying to get results if there are records where the date falls between two fields: start and finish. The linq query I have doesn't seem to return any results:
var alerts = from q in db.AlertMsgs
where (q.Start >= DateTime.Now
&& q.Finish <= DateTime.Now)
select q;
Any suggestions on why this is? I've also tried
var alerts = from q in AlertMsgs.Where(q => q.Start.CompareTo(DateTime.Now) > 0
&& q.Finish.CompareTo(DateTime.Now) < 1)
select q;
without any luck either.
You have your conditions backwards. Try:
var alerts = from q in db.AlertMsgs
where (q.Start < DateTime.Now && q.Finish > DateTime.Now)
select q;
Or, using the method syntax (and <=/>=, in case you want that comparison):
var alerts = db.AlertMsgs
.Where(q => q.Start <= DateTime.Now && q.Finish >= DateTime.Now);
This will give you all messages which have already started (Start < Now) and have not yet finished (Finish > Now). What you were searching for was messages which haven't started yet (or started exactly now), but which have already finished (or finished exactly now). This would only return an item which had the same start and end time, and where both times were exactly DateTime.Now.

c# lambda expression using Sum for multiple comparisons

I'm trying use the Sum method in a lambda expression for a comparison, but I want to use it for multiple comparisons. How do I accomplish this? I've looked at "Let" and "SelectMany", but I haven't been able to find an answer.
Below is what the code looks like:
return _dbContext.All<Table>()
.Where(table => table.CurrentLevel <= salesCriteria.MaxTableLevel)
.Where(table => table.Leg
.Where(leg=> salesCriteria.StartDate <= leg.AddDate)
.Where(leg=> leg.AddDate <= salesCriteria.EndDate)
.Sum(leg => leg.Width) <= salesCriteria.MaxGoalAmount);
As you can see, I'm trying to get all Tables with certain criteria that have Legs with certain criteria and whose width all add up to be less than a certain value. I would also like to make sure that the Sum is greater than a certain min value. However, I can't do that here since as soon as I do .Sum, I lose the list. So how would I accomplish that here? All I want is minValue <= .Sum() <= maxValue
It sounds like you want something like:
return _dbContext.All<Table>()
.Where(table => table.CurrentLevel <= salesCriteria.MaxTableLevel)
.Select(table => new {
table,
legWidth = table.Leg
.Where(leg=> salesCriteria.StartDate <= leg.AddDate)
.Where(leg=> leg.AddDate <= salesCriteria.EndDate)
.Sum(leg => leg.Width)
})
.Where(x => x.legWidth <= salesCriteria.MaxGoalAmount &&
x.legWidth >= salesCriteria.MinGoalAmount)
.Select(x => x.table);
So the Select here is the equivalent of using a let in a query expression.
As a query expression, this would be:
return from table in _dbContext.All<Table>()
where table.CurrentLevel <= salesCriteria.MaxTableLevel
let legWidth = table.Leg
.Where(leg=> salesCriteria.StartDate <= leg.AddDate)
.Where(leg=> leg.AddDate <= salesCriteria.EndDate)
.Sum(leg => leg.Width)
where legWidth <= salesCriteria.MaxGoalAmount &&
legWidth >= salesCriteria.MinGoalAmount
select table;
To get the power of let, you need to switch from method-chaining syntax to query expression syntax. Try this:
var goodTables =
from table in _dbContext.All<Table>()
where table.CurrentLevel <= salesCriteria.MaxTableLevel
let sumOfWidthOfGoodLegs =
table.Leg
.Where(leg=> salesCriteria.StartDate <= leg.AddDate)
.Where(leg=> leg.AddDate <= salesCriteria.EndDate)
.Sum(leg => leg.Width)
where sumOfWidthOfGoodLegs <= salesCriteria.MaxGoalAmount
// can insert another where on sumOfWidthOfGoodLegs here as required
select table;
return goodTables.ToList();
I note that this is checking the width-sum of only the good legs - I'm not convinced this is what you want, but it's what you're doing at present.

Categories