I am facing the problem to know if DateTime is between a date range in the dotnet.
For example if the x.SchedulerStart value is 2022-11-02 06:46:30 and x.SchedulerEnd value is 2022-11-02 23:26:30. I want check this DateTime.Today value is inside the date range, but below coding is doesn't work. I have look at this StackOverflow question still cannot work How to know if a DateTime is between a DateRange in C#
Below is my coding:
x.SchedulerStart.Date >= DateTime.Today && x.SchedulerEnd.Date <= DateTime.Today
Whole code:
List<SAASMsgSchedulerForQueueList> msgSchedulerList = await _saasdbContext.SaMsgScheduler.AsNoTracking().Where(x => (x.Enabled == true && x.SchedulerStart.Date >= DateTime.Today && x.SchedulerEnd.Date <= DateTime.Today) &&
((x.SchedulerRecurring == "Daily" && x.RecurringTime == currentTime) || (x.SchedulerRecurring == "Weekly" && x.RecurringWeekday == weekDayNumber && x.RecurringTime == currentTime) ||
(x.SchedulerRecurring == "Monthly" && x.RecurringDay == currentDay && x.RecurringTime == currentTime) || (x.SchedulerRecurring == "Yearly" && x.RecurringMonth == currentMonth && x.RecurringTime == currentTime)))
.Join(_saasdbContext.TnMsgTemplate.AsNoTracking(),
schedule => schedule.TemplateId,
template => template.Id,
(schedule, template) => new { schedule, template })
.Join(_saasdbContext.SaMsgQuery.AsNoTracking(),
schedule => schedule.template.QueryId,
query => query.Id,
(schedule, query) => new SAASMsgSchedulerForQueueList()
{
ID = schedule.schedule.Id,
BranchID = schedule.schedule.BranchId,
TemplateID = schedule.schedule.TemplateId,
TemplateContent = schedule.template.TemplateContent,
Query = query.QuerySql,
MessageType = schedule.schedule.MessageType,
RecurringDatetime = schedule.schedule.RecurringDatetime,
}).ToListAsync();
Hope some one can guide me on how to solve this problems. Thanks.
You need to reverse the condition. Right now you're looking for something that started after today and ended before today.
It's better to write the query in a form that reflects what you want, ie Today is between the start and end dates :
x.SchedulerStart.Date <= DateTime.Today && DateTime.Today <= x.SchedulerEnd.Date
Better, as in after 20 years I still mix things up if I put the field on the left side of such a query. One shouldn't have to translate an expression to understand what it does
Another improvement is to avoid .Date. This results in a cast(ScheduleStart as date) in SQL Server. Normally such a cast would prevent the use of indexes. SQL Server is smart enough to convert this into a range query but can't use any indexes gathered for the ScheduleStart column and can still end up with an inefficient execution plan.
.Date can simply be removed from DateTime.Today <= x.SchedulerEnd.Date. If the end date is today, DateTime.Today <= x.SchedulerEnd holds no matter the time.
To eliminate .Date from the opening date, compare it to the next day, ie x.SchedulerStart < DateTime.Today.AddDays(1). If the start day is today, that will hold for every time. If SchedulerStart is on the next day, the condition will still be false.
A correct and efficient condition will be :
x.SchedulerStart < DateTime.Today.AddDays(1)
&& DateTime.Today <= x.SchedulerEnd
The query is targeting MySQL using Oracle's official EF Core provider, MySQL.EntityFrameworkCore, which has several known problems, which are fixed on Oracle's own schedule. That's why almost everyone uses the truly open source Pomelo.EntityFrameworkCore.MySql. Everyone as in 29.3M downloads for Pomelo vs 1.7M downloads for Oracle's provider.
In this case, Oracle's provider fails to treat DateTime.Today.AddDays(1) as a constant and tries to convert it to a SQL expression.
To avoid this problem, calculate the dates before the query, eg:
var today = DateTime.Today;
var tomorrow = today.AddDays(1);
...
x.SchedulerStart < tomorrow && today <= x.SchedulerEnd
Related
I am trying to get a list with some data from SQL using Linq. The results in list are based on date which the user inputs.
My code for getting the list
TimologioList = Dao.SearchTimologiaNotSendToMydata(apoDateEdit.DateTime,
eosDateEdit.DateTime.Date.AddDays(1).AddMilliseconds(-1),
MainDoc.Xrisi,
DefaultDiasafistis.DiasafistisDefault,
apestalmenaCheckEdit.Checked);
public List<Timologio> SearchTimologiaNotSendToMydata(DateTime apoDate, DateTime eosDate, string xrisi, Diasafistis diasafistis, bool apestalmenaTimologia)
{
List<Timologio> timologia = db.Timologio
.Where(p => (p.Imerominia >= apoDate && p.Imerominia <= eosDate)
&& (p.Xrisi == xrisi && p.Diasafistis == diasafistis)
&& (!p.IsYpodeigma.HasValue || !p.IsYpodeigma.Value)
&& p.ArithmosTimologiou != 0)
.OrderByDescending(p => p.Imerominia).ToList();
return timologia;
}
The two variables have values apoDate = 1/1/2022 12:00:00 and eosdate = 31/1/2022 11:59:59.
When I run this query, it returns another result which has a date of 1/2/2022 and I don't understand why.
Values of the date variables:
SQL data:
Results in the program:
I am using DateTime.Date.AddDays(1).AddMilliseconds(-1) because I found that it gives more precise values in the date
I have a database with three tables and I am making a program that will select and need to display results from all three at the same time.
In order to speed up the getting of records I decided to make the requests async so that they can happen at the same time.
Since you cannot perform more than one concurrent operation on the same DB context, I just instantiate three contexts, in total, and start a Linq query "ToListAsync()" on each one.
But something weird (for me) happens - the async version wasn't any faster than the sync version. Whether I get the results asynchroniously with ".ToListAsync()" or synchronously with ".ToList()" they take the same amount of time. With the sync version, the first operation takes ~2s to complete while the second ~170ms and the third ~90ms. I suppose some sort of execution plan or caching or establishing the connection is what makes the first request take a lot of time while the others complete almost instanteniously but I'd like to know WHY exactly this happens and if there is a way to make it faster.
Forgot to mention the async version takes the same amount of time - 2s.
Relevant code:
int maxRecords = 10;
var resultsTableOne = dbContext.tableOne.Where(log =>
log.DateUtc >= dateFrom || dateFrom == null)
&& (log.DateUtc <= dateTo || dateTo == null))
.OrderByDescending(log => log.Id).Take(maxRecords).ToList();
var resultsTableTwo = dbContext.tableTwo.Where(log =>
log.DateUtc >= dateFrom || dateFrom == null)
&& (log.DateUtc <= dateTo || dateTo == null))
.OrderByDescending(log => log.Id).Take(maxRecords).ToList();
var resultsTableThree = dbContext.tableThree.Where(log =>
log.DateUtc >= dateFrom || dateFrom == null)
&& (log.DateUtc <= dateTo || dateTo == null))
.OrderByDescending(log => log.Id).Take(maxRecords).ToList();
The select conditions are simplified here. For the async version, the "ToList" is replaced with "ToListAsync", which returns a task on which "GetAwaiter().GetResult()" is called after the code shown here (and the "dbContext" is replaced with three separate instances).
P.S.
The results for the sync version are the same with one and three DbContexts. I.e. it takes the same amount of time whether all three operations are performed on the same instance or each on its own instance.
In order to speed up the getting of records I decided to make the requests async so that they can happen at the same time.
This isn't what the async/await pattern does. What you seem to want to do is parallelization, which you can use async methods and their associated Task, however this requires 3 distinct instances of a DbContext. As a very bare-bones example relative to the code you had:
using (var context1 = new AppDbContext())
{
using (var context2 = new AppDbContext())
{
using (var context3 = new AppDbContext())
{
var table1Task = context1.tableOne
.Where(log =>
log.DateUtc >= dateFrom || dateFrom == null)
&& (log.DateUtc <= dateTo || dateTo == null))
.OrderByDescending(log => log.Id)
.Take(maxRecords).ToListAsync();
var table2Task = context2.tableTwo
.Where(log =>
log.DateUtc >= dateFrom || dateFrom == null)
&& (log.DateUtc <= dateTo || dateTo == null))
.OrderByDescending(log => log.Id)
.Take(maxRecords).ToListAsync();
var table3Task = context3.tableThree
.Where(log =>
log.DateUtc >= dateFrom || dateFrom == null)
&& (log.DateUtc <= dateTo || dateTo == null))
.OrderByDescending(log => log.Id)
.Take(maxRecords).ToListAsync();
var resultTask = Task.WhenAll(table1Task, table2Task, table3Task);
try
{
resultTask.Wait();
var result1 = table1Task.Result;
var result2 = table2Task.Result;
var result3 = table3Task.Result;
// Use your 3 lists.
}
catch(Exception ex)
{// Handle any exception when running.
}
}
}
}
Each query must run on a separate DbContext as the DbContext is not thread safe.
As mentioned in the comments, there are far better things to be looking into for improving performance including indexing and using projection rather than returning entire entities. If Table1 rows are quite large with many large fields that aren't needed by the resulting code, projecting with Select to get just the columns you need can help deliver far more performant code. Parallelism is only something I would consider when faced with running several queries where one or more might take a substantial amount of time and the results from each are completely independent.
I want to return records where the date column is greater than DateTime.Now.AddDays(-3), but only if the type column is complete.
Meaning, I want to return everything except for records that are older than 3 days and the type is == complete (Enum 1).
It's almost as if I need Except, but for that, I'd need to enumerate the results, then I wouldn't have my page number of results (.Take(10)).
How would this be done in linq? I can't figure out how this query would look. I would like the query to be done SQL SERVER side as much as possible as to be efficient.
Just to be clear - I want all results, EXCEPT records that are completed and older than 3 days.
(completed meaning the type column value == 1 (Enum))
My project is .NetCore 3.1
Thanks
Could be this that you need ?
Var results = context.Entity.Where(x=> x.Type != enum.Completed ||( x.Type == enum.Completed && x.Date >=DateTime.Now.AddDays(-3)));
Maybe something like this?
Results = context.Entity.Where(x => x.Date > DateTime.Now.AddDays(-3) || x.Type != YourEnum.Complete);
I am not sure what you mean by "type" column, but I am guessing is the value of the object you are after.
Then you should probably do something like :
var dateRange = DateTime.Now.AddDays(-3);
var results = _repository.Entity.Where(w => w.Date >= date && w.Type != null);
I try to use LINQ to filter the data, the data is from 3rd party API (JIRA Server), and ResolutionDateis DateTime type, I guess it use Nullable, anyway, I am pretty sure the value is null, but when I use LINQ, it just not work at all. The LINQ just can't do i.ResolutionDate == null, it always said there is no item match this condition. I'm pretty sure I have the issues their ResolutionDate is null.
https://developer.atlassian.com/server/jira/platform/database-issue-fields/
var foo = datas.Where(i =>
i.Created > date && i.Created <= date.AddDays(7) &&
i.ResolutionDate> date.AddDays(7) && i.ResolutionDate== null);
You could probably coalesce those into (i.ResolutionDate?.Date > date.AddDays(7))
Ultimately, it should have some condition that will return true when you do the comparison.
You should check if the value of ResolutionDate is null OR more than seven days in the future
var foo = datas.Where(i =>
i.Created > date && i.Created <= date.AddDays(7) &&
(i.ResolutionDate == null || i.ResolutionDate > date.AddDays(7)));
I'm trying to filter a list according to give start and end date, sometimes it does give me proper rows according to the info I've entered, sometimes not. Below is my query does anybody see any problem in logic?
public List<MyTicket> FilteredTickets => Tickets.Where(x =>
(string.IsNullOrEmpty(TicketType) || x.RequestTypeId == TicketType) &&
(StartDate == null || x.DateLogged >= StartDate) && (EndDate == null || x.DateLogged <= EndDate)).ToList();
You need to fix as follows:
public List<MyTicket> FilteredTickets =
Tickets.Where(x =>
(!string.IsNullOrEmpty(TicketType) && x.RequestTypeId == TicketType) &&
(StartDate != null && x.DateLogged >= StartDate) &&
(EndDate != null && x.DateLogged <= EndDate)).ToList();
You are currently checking if your StartDate and EndDate values are null or greater instead of not null and greater :
public List<MyTicket> FilteredTickets => Tickets.Where(x =>
(string.IsNullOrEmpty(TicketType) || x.RequestTypeId == TicketType) &&
(StartDate != null && x.DateLogged >= StartDate) &&
(EndDate != null && x.DateLogged <= EndDate))
.ToList();
So as soon as your previous expression was being evaluated, it would see that one of these date fields was null and evaluate the entire section as true, thus displaying the result as opposed to filtering it out.
It's a dropdown list so it has to allow the user to leave it blank (null) so that wasn't an error, but apparently the problem is since it was invoking the get method, instead of the post, it was getting confused with date and time format. I've found some of the answers about setting up the global settings and culture in order to solve this problem. MVC DateTime binding with incorrect date format