DateTime.Date conversion in EF Core Generated Query - c#

We have a project we are working on and we need to query the database for some data for a particular date.
We configured our DB to read and write date as UTC.
When writing the query to get the data, I noticed that the data for a date was not being pulled from the database.
Here is the code:
transactionDate = Convert.ToDateTime("2021-11-10:T10:00:00").ToLocalTime();
var transactions2 = _transactionsRepo.Query()
.Where(transaction => transaction.AccountId == pharmacy.AccountId.Value)
.Where(transaction => transaction.TransactionDate.Date == transactionDate.Date)
.OrderByDescending(transaction => transaction.TransactionDate)
.Skip(numToSkip)
.Take(pageSize);
On investigation, I noticed that when pulling the data, the DB returns the date as UTC as it should and the date is compared to the input date. But no data is returned. I checked the query generated and noticed this:
DECLARE #__transactionDate_1 datetime = '2021-11-10T10:00:00.000';
DECLARE #__p_2 int = 0;
DECLARE #__p_3 int = 10;
SELECT *
FROM [WalletTransactions] AS [w]
WHERE ([w].[AccountId] = #__AccountId_Value_0) AND (CONVERT(date, [w].[TransactionDate]) = #__transactionDate_1)
ORDER BY [w].[TransactionDate] DESC
OFFSET #__p_2 ROWS FETCH NEXT #__p_3 ROWS ONLY
From the above, the query generated shows that the TransactionDate is converted to just Date and compared to the input date #__transactionDate_1 which is in DateTime form.
Any help on how to solve this will be deeply appreciated.

For anyone facing the same issue, here is a link to the resolution on EF core repo on github:
https://github.com/dotnet/efcore/issues/28380
The issue was caused by a custom value converter that saves and reads all date as UTC.
This means a double conversion was happening and skewing the date time.
Solution is to specify that the input date is in UTC and hence should not be converted.

Related

Unable to select records between date range

In my Windows Form C# Application, I am inserting the record into the SQL server database. Along with other fields, I am also inserting both the current date and current time using the following format:
DateTime currentDate = DateTime.Now;
string SaleDate = currentDate.ToString("dd-MM-yyyy");
DateTime currentTime = DateTime.Now;
string SaleTime = currentTime.ToString("hh:mm:ss tt");
Which works fine and the records are inserted successfully with Date and Time format like .
However, when I select records between two dates, I am unable to perform this operation. I am sure that there is no problem in this custom format of my date because I have edited the same format several times and even I have saved the date in its default format but still I am unable to select the target records (between two dates)
I am using the following select query in my application to select records from the view vAllSales which results in selecting either all the records or records whose SaleDate does not meet the specified filter criteria:
select * from vAllSales where SaleDate >= '20-04-2019' and SaleDate <= '30-04-2019'"
I have tried the following queries in my SQL server as well to inspect the cause:
1.
select * from vAllSales where SaleDate between '21-04-2019' and '09-05-2019'
The above query does not return any value. Like
2.
select * from vAllSales where SaleDate >= '21-04-2019'
The above query select only a few records. Because 21-04-2019 is the initial SaleDate and the query should return all of the Sales but it only returns a few records, like .
Is there any issue with the specified date format within my code? Or do I have to work on improving my queries? I need a more professional and reliable approach for this case.
You should store your date and time as datetime2 objects in your database.
It will give you the benefits of:
better sorting: (your current string format does not allow a natural sort)
better performance; since your date and times are represented as numbers in stead of strings
easier to handle in code and queries: since it maps directly to a C# DateTime object.
For more info on database types see:
https://learn.microsoft.com/en-us/sql/t-sql/data-types/datetime2-transact-sql?view=sql-server-2017
And perhaps:
https://learn.microsoft.com/en-us/sql/t-sql/data-types/time-transact-sql?view=sql-server-2017
If you absolutely must use a string to represent your date, make sure it's in the sort-able ISO format.
YYYY-MM-DD
due to the nature of this format it's lexicographical sort-able as a string type.
You are trying to apply logical operations to string values. What will here happen is lexicographical comparing. (left to right).
So you better use correct data types to store data in table.
But If you really want to store date as a string, you have to cast them to proper data types before comparison.
select * from vAllSales where CAST(SaleDate AS DATE) >= '21-04-2019'
Keep note that ms sql server uses single quotes for pass datetimes. That doesn't mean those are strings or varchar

asp.NET and SQL Server datetime issues

I am having hard time to store date information into the datetime column of SQL Server.
I get the input from the user for three columns:
Creation Date
Preparation Date
Next Preparation Date
I use calendarextender and format the date as "yyyy/MM/dd". When all the fields have date, they are stored in the DB as for instance, 16-10-2016 (dd-MM-yyyy).
At this point I have two issues:
These columns are optional, when some of them are empty my code does not work (I assume because datetime cannot be null). To overcome this, I am using the following code snippet but still does not work.
DateTime? creationDate= null;
if (creationDateTextbox.Text != null && creationDateTextbox.Text != "")
{
creationDate= Convert.ToDateTime(creationDateTextbox.Text);
}
When I fetch the dates from DB, they are shown as 10/16/2016 (MM-dd-yyyy) which is different how I formatted it. I would like to show it in the format user enters them.
Dates do not have a format while stored in a database. It is actually usually just a very large long that counts the number of milliseconds from a set starting date.
If you want to store the format you need to stop storing it as dates and instead just treat the text as text in the database, however if you do this you won't get the advantage of sorting or filtering by a date range because it will just be seen as text.
Date time doesn't have any format You can format is as a string, suppose your DateTime type database field dt which contain date as 10/16/2016 (MM-dd-yyyy) then you can convert it
string s = dt.ToString("yyyy/MM/dd");
The answer to one of your questions is here: MSDN
You can use data annotations to format the dates that you get from your SQL DB. I'm assuming that you're using EF6; if not, you can change the field to a varchar in SSMS, and store the date as a String.
And the second, I'm unclear about, but if what you want is for your SQL DB column to be optional, you can use the Optional data annotation for that.

How to compare date with string in Linq with MVC4?

Hi I am developing one MVC$ application. I came across one query. In one of my database table I have datetime column. I will be storing data as below in that column.
Eg: 2016-10-05 11:57:54.650
I have one jquery calender where i will receive date as string. I will receive in the below format.
eg: 06/10/2016
I have below Linq query where I am comparing my jquery date with database date as below.
Below code I have tried so far.
string datemodified;
DateTime dt = Convert.ToDateTime(datemodified);
upld_id = (from c in db.upldTable where c.upld_clientid==clientId && EntityFunctions.TruncateTime(c.upld_ModifiedDateTime) == dt select c.upld_docid).ToArray();
My query does not work fine. My query not returning expected result. I am having problem in comparing date portion. If i did not compare date then my query works as expected. So I am sure my date comparision is not happening above. Can someone help me in this regard? Thanks a lot.

C# Program want to select data <= 23:59:59 but ends up selecting data with 00:00:00 timestamp as well

this is my first question so pardon any mistakes that might occurs :)
I made a C# program that collects data from SQL Server Database using Datatables, and then export the results to Excel spreadsheets using Interop.
The program itself runs well and doing as it should; however, I found some bugs when it tries to select data with Date columns less than or equal to i.e. 2014-05-31 23:59:59.
Supposed I tried to get all data up to May 1st 2014.
My code first initiates the "Start Date" parameter for the SQL Command later used like this:
var firstDay = new DateTime(today.Year, today.Month, 1); //2014-05-01 00:00:00`
based on firstDay, it initiates the date for the parameter
var periodTo = firstDay.AddSeconds(-1);`
I debugged and got the time I wanted: 2014-04-30 23:59:59
After adding some more parameters for the data criteria, it executes the method to run the query using the parameters supplied.
queryResult = medicore.GenerateRegister(ConfigurationManager.AppSettings["queryDir"], ConfigurationManager.AppSettings["queryName"]);`
The periodTo parameter will be mapped to #EDate variable in the SQL Script. #EDate is declared as Datetime. The #Edate comes into play here:
Select columns
From tables
Where Voucher.Date <= #EDate
which I suppose, the script will be looks like Where Voucher.Date <= '2014-04-30 23:59:59'
The problem is, the result in the Excel file generated also consists of data from '2014-05-01', which is not supposed to be there...at least based on the criteria I set.
Is there some kind of rounding happened between C# and SQL Server?
Thanks!
The reason for this is probably that Voucher.Date is a SMALLDATETIME, therefore you are implicitly converting '2014-04-30 23:59:59' to a SMALLDATETIME:
SET DATEFORMAT MDY;
SELECT CONVERT(SMALLDATETIME, '2014-04-30 23:59:59')
Which gives '2014-05-01'.
Why not just use the Less than operator, instead of less than or equal to?
SET DATEFORMAT MDY;
SELECT ...
WHERE Voucher.Date < '2014-05-01';
N.B I have explcilty stated the DATEFORMAT because yyyy-MM-dd (despite being an ISO standard) is not culture invariant for the DATETIME and SMALLDATETIME data types in SQL Server, and if (like me) you are in a country where the default date format is DMY then SELECT CONVERT(SMALLDATETIME, '2014-04-30') will give you a conversion error. yyyyMMdd is the only culture invariant date format for these two types.
An excellent, and very relevant article to read is Aaron Bertrand's Bad habits to kick : mis-handling date / range queries

Searching for records on one exact day

In UI I have two date picker fields that user can select start and end date of his search. ( No time value entry, just date part) So for example he can enter the same date for both start and end of his criteria if he wants to only see the records for that one specific date.
Now in SQL Server those columns are stored as DateTime fileds with values like
'2013-04-04 10:48:02.830'
So because it keeps the time part in SQL Server too, then my searches return no result when the start and end date is the same in C# part.
How can I fix this on C# side? ( I am assuming there is a use case for the time part that we keep in SQL Server in some other part of the application so don't want to mess with back-end section).
So: SQL Server has values like '2013-04-04 10:48:02.830'
C# is passing values like {11/26/2011 12:00:00 AM}
And when the start and end date are the same, we get no results.
Assuming you have code on the back end that go to SQL Server for you, instead of having a UI that is data bound:
You simply take the two values you get from the UI and modify them as needed:
DateTime from = originalFromDate.Date;
DateTime to = originalToDate.Date.AddDays(1).AddSeconds(-1);
and now if you search for anything that is between from and to, you'll find your records:
(in case of LINQ:)
var query = queryUntilNow.Where(x => x.Date >= from && x.Date <= to);

Categories

Resources