SqlParameter Datetime SqlValue difference with Value - c#

I have a datetime value to pass into a SqlParameter.
DateTime object value
However when pass to myCmd.Parameters.Add("#TrxDate", adt_TrxDate);
SqlParameter SqlValue & Value property is difference value
Found that it add a day when executing query. I found this issue in profiler and finally find out SqlParameter SqlValue & Value property is different value. Why it is happen and any idea?

Root cause is, .NET DateTime has higher precision then SQL Server's DateTime. So it is rounded off. SQL Server 2008 on wards, DateTime2 supports higher precision.
Since data type is DateTime in SQL, SQL Parameter is rounding .net DateTime to nearest Sql DateTime. Since it is rounding algorithm, it may add .003,.007 or remove, you can look at this SO question for more details. Undesired rounding of DateTime in SQL Server , so sometimes, if added micro seconds adds up, it may actually change to next day if it was on boundary between two days.
From MSDN,
https://msdn.microsoft.com/en-us/library/system.data.sqldbtype(v=vs.110).aspx
DateTime. Date and time data ranging in value from January 1, 1753 to December 31, 9999 to an accuracy of 3.33 milliseconds.
DateTime2
Date and time data. Date value range is from January 1,1 AD through December 31, 9999 AD. Time value range is 00:00:00 through 23:59:59.9999999 with an accuracy of 100 nanoseconds.
So I guess if you change Parameter Type to DateTime2 it would preserve actual time. However, unless your SQL Server has column's type as DateTime2, it this will have no effect.

You have to use like the following by specifying the SqlDbType for the parameter :
myCmd.Parameters.Add("#TrxDate",SqlDbType.Date).Value =adt_TrxDate;
use SqlDbType.DateTime if it is DateTime
or you can use AddWithValue
myCmd.Parameters.AddWithValue("#TrxDate",adt_TrxDate);
You can refer this thread for the difference between these two

Related

How to remove time in date time?

How to remove a time in date time ? on column date its only display format
I store the value on repository combobox dropdown, and it store the value including the time. How do I remove the time?
I know there's so many question about this. But the solution was by converting it into a date.tostring("dd MMM yyyy"). Is there a solution beside convert it into string? I want the value was date time not a conversion of string.
The code I am using still giving me a time.
DateTime date = Convert.ToDateTime(gridView1.GetDataRow(i)["date"]);
You just forgot to specify the date at the end of the conversion
DateTime date = Convert.ToDateTime(gridView1.GetDataRow(i)["date"]).Date;
DateTime as the name implify, stores date and time.
You cannot remove time part from date because time is an integral part of date.
To understand this you will have to understand how the date and time are stored. Internally, the date and time is stored as a rational number (in fractions). In computer system 24 hours are considered as numeric 1, so when your value is increased by 1 that means your date is increased by 1 day. If the value is increased by 0.5 that means your date is increased by 12 hours (half day).
So, when you have value 42613.00 that means 31st August at midnight (just when the day started) and if you have value 42613.25 that means 6 AM of 31 Aug 2016 and 42613.50 means 12 noon of 31 Aug 2016 (and 42613.39236 means 9:25:00 AM of 31 Aug 2016)
The smallest fraction of time that need to be stored is 1 millisecond. That means the values of DateTime field should have a precision of more than 0.0000000115740740740741. But this is an irrational value (in binary) and hence cannot be stored as such (the nearest match is 1.00000000000000000000000000110001101101011101010000111010111111..., ... means there are more), so I can say that milliseconds are to their nearest approximation values.
.
That said,
if you wish to take only Date part, you can create your own class or struct to store date part of the DateTime and then override operators for date arithematic and provide implicit conversions to convert them to DateTime if any code that expect DateTime field.

C# DateTime to SQL DateTime losing precision

Have a small problem where if I save a DateTime field as an SQL command parameter it loses precision, like often less than a milisecond.
e.g. The parameter's Value is:
TimeOfDay {16:59:35.4002017}
But its SqlValue is:
TimeOfDay {16:59:35.4000000}
And that's the time that's saved in the database.
Now I'm not particularly bothered about a couple of microseconds, but it causes problems later on when I'm comparing values, they show up as not equal.
(Also in some comparisons the type of the field is not known until run-time so I'm not even sure at dev-time whether I'll even need special DateTime "rounding" logic)
Is there any easy fix for this when adding the parameter?
You're using DateTime, which is documented with:
Accuracy: Rounded to increments of .000, .003, or .007 seconds
It sounds like you want DateTime2:
Precision, scale: 0 to 7 digits, with an accuracy of 100ns. The default precision is 7 digits.
That 100ns precision is the same as DateTime (1 tick = 100ns)
Or just live with the difference and write methods to round DateTime before comparing - that may end up being simpler.
Try using datetime2 it has better precision.

Accuracy of comparing DateTime.now of C# and GetDate() from SQL

What i am doing is that, i need to select a row that i have just recently added through DateTime to get the PK since i need it.
I store the DateTime through:
DateTime nw = DateTime.now and i use nw to search through my table.
My question is that, what if let's say i put 2 rows within a span of 1 minute?
My sql table stores them like this:
Since milliseconds isn't visible, will both of them be selected?(assuming everything happened within 1 minute)
Edit: this is from my asp mvc project. So the DateTime is new everytime my action is run.
The problem is precision. The GetDate() function in TSQL is not at the precision as c# DateTime, as GetDate() returns an TSQL DateTime.
TSQL DateTime:
Defines a date that is combined with a time of day with fractional seconds that is based on a 24-hour clock.
Rounded to increments of .000, .003, or .007 seconds
C# DateTime:
The Ticks property expresses date and time values in units of one ten-millionth of a second, and the Millisecond property returns the thousandths of a second in a date and time value. However, if you are using repeated calls to the DateTime.Now property to measure elapsed time, and you are concerned with small time intervals less than 100 milliseconds, you should note that values returned by the DateTime.Now property are dependent on the system clock, which on Windows 7 and Windows 8 systems has a resolution of approximately 15 milliseconds.
However you could use the newer (avail as of SQL Server 2008) SysDateTime() which returns a datetime2(7) value that should match the precision of C# Datetime.
datetime2(7):
Defines a date that is combined with a time of day that is based on 24-hour clock. datetime2 can be considered as an extension of the existing datetime type that has a larger date range, a larger default fractional precision, and optional user-specified precision.
This only academically interesting because you should never use a datetime as a PK.
Let's say it's Nov 6, 2016 at 1:15AM. You create a record:
MyPk
------
2016-11-06 01:15:00
One hour later you create another record...
MyPk
------
2016-11-06 01:15:00
2016-11-06 01:15:00
Duplicate PKs due to daylight savings. Don't have daylight savings? There are a multitude of reasons to not use DateTime for a PK (simply google search for datetime as primary key).
Just to name a few:
Exact select can be very difficult (milliseconds matter!)
Foreign Keys become a Nightmare
Replication is very difficult unless all systems are in the same timezone
If you really want to use the DateTime.Now with second precision as a way to find the PK of your data, you should not declared it once and use it everywhere. Rather, you should use it like this:
insertDataToDataBase(data, DateTime.Now);
and then 10-20 seconds later
insertDataToDataBase(data, DateTime.Now); //still use DateTime.Now
This way your DateTime.Now will always be updated

How to compare sql datetime and c# datetime

This was born from my previous question
I have a DateTime in c#.
Then this value is inserted to database.
After that select this value and compare that date is the same as it was in the beginning.
What is the best way to do this?
Since SQL datetime has different ticks, DateTime from the first step will not be the same as SQL DateTime (row["MyDate"])
How to compare them?
Subtract one from the other & check the ticks of the resulting TimeSpan to be within acceptable limits for the difference in tick length
You can use the SqlDateTime structure.
DateTime now = DateTime.Now;
SqlDateTime sqlNow = new SqlDateTime(now);
bool equal = now == sqlNow.Value; // false
So if you have a DateTime and want to know if it's equal to a DB-DateTime use:
Assert.Equal(dbEndTime, new SqlDateTime(endTime).Value); // true
SqlDateTime:
Represents the date and time data ranging in value from January 1,
1753 to December 31, 9999 to an accuracy of 3.33 milliseconds to be
stored in or retrieved from a database. The SqlDateTime structure has
a different underlying data structure from its corresponding .NET
Framework type, DateTime, which can represent any time between
12:00:00 AM 1/1/0001 and 11:59:59 PM 12/31/9999, to the accuracy of
100 nanoseconds. SqlDateTime actually stores the relative difference
to 00:00:00 AM 1/1/1900. Therefore, a conversion from "00:00:00 AM
1/1/1900" to an integer will return 0.
if you ignore millisecond difference than you can try this
Select * from MyTable DATEADD(ms, -DATEPART(ms, endTime), endTime) = #value

Milliseconds in my DateTime changes when stored in SQL Server

I have a date time that I generate like this:
DateTime myDateTime = DateTime.Now;
I then store it in the database (in a DateTime typed column) with Entity Framework. I then retrieve it with OData (WCF Data Services).
When it goes in the TimeOfDay value is: 09:30:03.0196095
When it comes out the TimeOfDay value is: 09:30:03.0200000
The net effect of this makes it so that the Milliseconds are seen as 19 before it is saved and 20 after it is re-loaded.
So when I do a compare later in my code, it fails where it should be equal.
Does SQL Server not have as much precision as .NET? Or is it Entity Framework or OData that is messing this up?
I will just truncate off the milliseconds (I don't really need them). But I would like to know why this is happening.
This really depends on the version of SQL server you are using.
The resolution of the date time field is to 3 decimal places: For example: 2011-06-06 23:59:59.997 and is only accuracte to within 3.33 ms.
In your case, 09:30:03.0196095 is being rounded up to 09:30:03.020 on storage.
Beginning with SQL 2008, other data types were added to provide more detail, such as datetime2 which has up to 7 decimal places and is accurate to within 100ns.
See the following for more information:
http://karaszi.com/the-ultimate-guide-to-the-datetime-datatypes
I think your best bet is to provide the rounding to the second PRIOR to storing it in SQL server if the milliseconds is unimportant.
This is due to the precision of the SQL datetime type. According to msdn:
Datetime values are rounded to increments of .000, .003, or .007 seconds
Look at the Rounding of datetime Fractional Second Precision section of this msdn page and you'll understand how the rounding is done.
As indicated by others, you can use datetime2 instead of datetime to have a better precision:
datetime time range is 00:00:00 through 23:59:59.997
datetime2 time range is 00:00:00 through 23:59:59.9999999
For those who do not have the ability to use DateTime2 in SQL (ex: like me using tables that are generated by a separate system that would be expensive to change for this single issue), there is a simple code modification that will do the rounding for you.
Reference System.Data and import the System.Data.SqlTypes namespace. You can then use the SqlDateTime structure to do the conversion for you:
DateTime someDate = new SqlDateTime(DateTime.Now).Value;
This will convert the value into SQL ticks, and then back into .NET ticks, including the loss of precision. :)
A word of warning, this will lose the Kind of the original DateTime structure (i.e. Utc, Local). This conversion is also not simply rounding, there is a complete conversion including tick calculations, MaxTime changes, etc.. So don't use this if you are relying on specific indicators in DateTime as they could be lost.
The precision of DateTime in SQL Server is milliseconds (.fff). So 0.0196 would round to 0.020. If you can use datetime2, you get a higher precision.

Categories

Resources