linq to sql lambda - syntax for not in where condition - c#

I want to use '!' to exclude the following records in my .Where.
What is the syntax?
// where do I put the ! to get the syntax correct
.Where(p => p.StartDate >= startDate && p.EndDate <= DateTime.Now.Date)

.Where(p => !(p.StartDate >= startDate && p.EndDate <= DateTime.Now.Date))
OR
.Where(p => p.StartDate < startDate || p.EndDate > DateTime.Now.Date)

Related

Combining multiple ef6 linq queries

I'm having an issue with combining multiple ef6 linq queries
Here the code works when the two linq queries are separated
List<int> skipRoomIds = hbContext.Reservations.Include(x => x.Room)
.Where(x => (x.FromDate < fromDate && fromDate < x.ToDate) || (x.FromDate < toDate && toDate < x.ToDate) ||
(fromDate < x.FromDate && x.FromDate < toDate) || (fromDate < x.ToDate && x.ToDate < toDate))
.Select(x => x.Room.Id).ToList(); //First query
roomRows = hbContext.Rooms.Where(x => !skipRoomIds.Contains(x.Id) && x.MaxNumOfPeople >= numOfPeople)
.Select(x=> new RoomRow() { From = fromDate, To = toDate, Room = x}).ToList(); //Second query
But when I try and combine the two I get an error:
System.NotSupportedException: 'LINQ to Entities does not recognize the method 'System.Linq.IQueryable`1[HotelBooker.Models.Reservation] Include[Reservation,Room](System.Linq.IQueryable`1[HotelBooker.Models.Reservation], System.Linq.Expressions.Expression`1[System.Func`2[HotelBooker.Models.Reservation,HotelBooker.Models.Room]])' method, and this method cannot be translated into a store expression.'
In the first linq query I get a list of integers to then use to check something in the where part of the second linq query, but then when I put the first linq query inside the second one it doesn't work.
Why would I want that ? well so I don't send more requests to the sql server then necessary.
roomRows = hbContext.Rooms.Where(z => !hbContext.Reservations.Include(x => x.Room)
.Where(x => (x.FromDate < fromDate && fromDate < x.ToDate) || (x.FromDate < toDate && toDate < x.ToDate) ||
(fromDate < x.FromDate && x.FromDate < toDate) || (fromDate < x.ToDate && x.ToDate < toDate))
.Select(x => x.Room.Id).AsEnumerable().Contains(z.Id)
&& z.MaxNumOfPeople >= numOfPeople)
.Select(z => new RoomRow() { From = fromDate, To = toDate, Room = z }).ToList();
Can anybody explain why combining multiple linq queries doesn't work with ef6 or if I'm doing it wrong ? and how would you do select statements in where or select part of an sql statement in linq ef6 ?
Sql statement example:
select * from table where id in (select id in table2);
I have tried searching for the answer but couldn't find anything, perhaps I had the wrong keywords when searching the problem.

How to filter only when date is not null using optional condition

I am a little confused about how I can use the date as an optional condition.
if there is a date then <= of date, if the date is null then don't filter based on date.
My code is like this
DateTime date= DateTime.UtcNow.AddDays(-10);
foreach (var camEvent in dbContext
.CAM_EVENTS
.Where(c => c.USER_ID == userID &&
c.CAM_ID == cam.CAM_ID &&
c.EVENT_DATE >= date) // I want to change this like
.OrderByDescending(c => c.DATE))
{...}
I want that line to look something like this
(date && c.EVENT_DATE >= date)
so it only filter when date is not null, but this is not working.
I'd do the following logic:
(date==null || (c.EVENT_DATE >= date))
You can do something like this:
DateTime date = DateTime.UtcNow.AddDays(-10);
var filteredContext = dbContext
.CAM_EVENTS
.Where(c => c.USER_ID == userID &&
c.CAM_ID == cam.CAM_ID)
.OrderByDescending(c => c.DATE);
if (date != null) {
filteredContext = filteredContext.Where(c.EVENT_DATE >= date);
}
foreach (var camEvent in filteredContext) {
...
}
You can use a ternary operator, also known as a conditional operator.
foreach (var camEvent in dbContext
.CAM_EVENTS
.Where(c => c.USER_ID == userID &&
c.CAM_ID == cam.CAM_ID &&
// if date is not null, it will return bool c.EVENT_DATE >= date, otherwise just true
(date != null ? c.EVENT_DATE >= date : true))
.OrderByDescending(c => c.DATE))

how to write linq query with where clause to get records between 9 am to 5 pm

how to write a linq query with to get records between 9 am 5 pm only. the records beyond that should be discarded.
timestamp datatype
code
var items = Pirs.Where(a => !a.dataFrame.EndsWith("AAAAAAAAAAA=") && (fromDate == null || fromDate.Value.Date <= TimeZoneInfo.ConvertTimeFromUtc(Convert.ToDateTime(a.timestamp), TimeZoneInfo.FindSystemTimeZoneById("India Standard Time")).Date) && (toDate == null || toDate.Value.Date >= TimeZoneInfo.ConvertTimeFromUtc(Convert.ToDateTime(a.timestamp), TimeZoneInfo.FindSystemTimeZoneById("India Standard Time")).Date))
.GroupBy(a => a.dataFrame.Substring(a.dataFrame.Length - 12))
.Select(g => g.First()).OrderBy(a => a.timestamp);
Pirs.Where(a.timestamp.TimeOfDay > new TimeStamp(9, 0, 0) && //all times after 9am
a.timestamp.TimeOfDay < new TimeStamp(17, 0, 0) && //all times before 5pm
a.timestamp.Date > fromDate && //all dates after fromData
a.timestamp.Date < toDate) //all dates before toDate
Do the following in where condition
TimeSpan span = TimeSpan.Parse("09:00:00");
TimeSpan espan = TimeSpan.Parse("17:00:00");
Pirs.Where(a => a.timestamp >= startDate && a.timestamp <= toDate && a.timestamp.TimeOfDay >= span && a.timestamp.TimeOfDay <= espan);

Two LINQ statements that should return the same thing are not

This is for LINQ to SQL
Here is the first query:
var rc = from site in customer.OrganizationSites
from gt in site.GeneralTransactions
where (gt.DealPackage.PackageTransactionDetail.StartDate <= periodStart
&& gt.DealPackage.PackageTransactionDetail.EndDate >= periodEnd)
|| (gt.DealPackage.PackageTransactionDetail.StartDate >= periodStart
&& gt.DealPackage.PackageTransactionDetail.EndDate <= periodEnd)
&& gt.IsVerified.HasValue
&& gt.IsVerified.Value
&& (!gt.Invoices.Any()
|| !gt.Invoices.Any(i => i.StartDate >= periodStart && i.EndDate <= periodEnd))
select gt;
Here is the second:
var rc = from site in customer.OrganizationSites
from gt in site.GeneralTransactions
where (gt.DealPackage.PackageTransactionDetail.StartDate <= periodStart
&& gt.DealPackage.PackageTransactionDetail.EndDate >= periodEnd)
|| (gt.DealPackage.PackageTransactionDetail.StartDate >= periodStart
&& gt.DealPackage.PackageTransactionDetail.EndDate <= periodEnd)
&& gt.IsVerified.HasValue
&& gt.IsVerified.Value
select gt;
rc = from gt in rc
where !gt.Invoices.Any()
|| !gt.Invoices.Any(i => i.StartDate >= periodStart && i.EndDate <= periodEnd)
select gt;
The second one simply does the first one in two steps but the second one returns what I'm actually looking for (in this case, nothing), I think I'm making an error somewhere but can't see where. I'd greatly appreciate if anyone could point out why.
Your first query has a top-level ||. Combining a || b and c should give (a || b) && c, but you're making it a || b && c, meaning a || (b && c).

LINQ DateTime Query that ignores milliseconds

x.CreateDate DateTime is stored in our database down to milliseconds. My dateTimePicker values startdate and enddate only allows for querying down to seconds.
How can change my query to ignore the milliseconds of x.CreateDate? I thought the code I wrote below would work but it is not.
if (stardDateIsValid && endDateIsValid && startdate == enddate)
query = _context.Logs
.Where(x => x.ApplicationID == applicationId &&
x.CreateDate.AddMilliseconds(-x.CreateDate.Millisecond) == startdate)
.OrderByDescending(x => x.ID)
.Take(count);
var query = from l in _context.Logs
where l.ApplicationID == applicationId
&& SqlMethods.DateDiffSecond(l.CreateDate,startdate) == 0
orderby l.ID descending
select l).Take(count);
This avoids converting every date in you table into a string and the subsequent string comparison, by comparing the two dates as dates.
Getting CreateDate and startdate in the same format will help you compare apples to apples. This should accomplish that.
if (stardDateIsValid && endDateIsValid && startdate == enddate)
query = _context.Logs
.Where(x => x.ApplicationID == applicationId &&
x.CreateDate.ToString(#"MM/DD/YYYY h:mm:ss") == startdate.ToString(#"MM/DD/YYYY h:mm:ss")
.OrderByDescending(x => x.ID)
.Take(count);
I have no idea why I could not get any results from the queries posted above as I tried several variations of their themes. However I did get it working correctly by adding milliseconds to the startdate and enddate variables and it s working.
if (stardDateIsValid && endDateIsValid)
startdate = startdate.AddMilliseconds(000);
enddate = enddate.AddMilliseconds(999);
query = _context.Logs.Where(x => x.ApplicationID == applicationId && x.CreateDate >= startdate && x.CreateDate <= enddate).OrderByDescending(x => x.ID).Take(count);
You can create extension method.
public const long TicksPerMillisecond = 10000;
public const long TicksPerSecond = TicksPerMillisecond * 1000;
public static bool IsEqualIgnoreMilliseconds(this DateTime date, DateTime compareDate)
{
long tickDiff = date.Ticks - compareDate.Ticks;
return tickDiff > 0 ? tickDiff < TicksPerSecond : tickDiff < -TicksPerSecond;
}
Then you can use this:
if (stardDateIsValid && endDateIsValid && startdate == enddate)
query = _context.Logs
.Where(x => x.ApplicationID == applicationId &&
x.CreateDate.IsEqualIgnoreMilliseconds(startdate)
.OrderByDescending(x => x.ID)
.Take(count);

Categories