Conversion in SqlDbType.DateTime2 is approximative - c#

I'm working in C# and I need to add a value in a row of my SQL database. The value needs to be of type DateTime2. So I have to do things that way :
query.Parameters.Add("Expiration", SqlDbType.DateTime2).Value = expiration; because expiration is of type DateTime. When it's done, I can execute my query without any problem.
But the value inserted in the database is not strictly the same than the value expiration. expiration equals to {09:48:47.6721345} and the value in the database is {09:48:47.6720000}. So there's fractional seconds missing, because of the conversion.
How can I manage that problem ?

as you specified the field in the database is datetime and the value that you are sending is datetime2 so the insertion query will send a datetime2 value but the result will be saved as datetime
according to the docs datetime has .123 for precision where datetime2 has .1234567

You mentioned that
expiration is of type DateTime
If that's the case, your truncation happened when you create the expiration object, who then pass that truncated value to the database.
By the way, when you mention
expiration equals to {09:48:47.6721345}
Did you see that value in a debugger, or is that the value you're trying to set expiration to (if the latter, the DateTime would've truncated to {09:48:47.6720000}, hence the value you see in the database).

I managed to solve my problem. In SQL datetime millisecond values are truncated.

Related

Why does setting a nulalble DateTime to DateTime.Max cause a pgsql parsing error?

When I set a nullable date time to DateTime.Max and save it to a database field of postgres type
timestamp without time zone
it saves it as
10000-01-01 00:00:00
Then when I reload a page that merely reads from this table I get the following error:
System.InvalidCastException: Specified cast is not valid.
a) Is DateTime? the correct C# conversion type?
b) What is the best way to set the DateTime value?
I checked the docs here http://www.postgresql.org/docs/9.2/static/datatype-datetime.html and it specifies the max value is 294276 AD... but that's lower than is currently set so it can't be that breaking it. I am using the latest version of NpgSql and entity framework
Many thanks
The problem lies within your C# code. According to MSDN:
The DateTime.MaxValue field represents the largest possible value of
DateTime, which is December 31, 9999 in the Gregorian calendar.
Your date value is just above this value, hence the exception.
I would suggest explicitly saving a very large date value in the database, e.g. December 31, 9999, in case the date value is not available.

c# SQL Server : DATETIME datatype

I am writing a unit test which stores an object with a DateTime parameter into a DATETIME2 SQL Server database column. I then create a temporary DateTime object called new_date_time and set that value to DateTime.Now.
The new_date_time value is then used to update the previous value and the SQL query to do this completes successfully.
When re-reading the object back from the database I receive the correct datetime values for days/hours/minutes but the .Ticks value is different from the new_date_time variables .Ticks property. The value returned from the read call returns the last 4 digits of the .Ticks property as zeros.
Why is this rounding occurring making my Assert.AreEqual fail?? :)
Thanks
I guess you are using Parameters.AddWithValue when writing the date to Sql Server. From MSDN the inferred type of a CLR DateTime is SqlDbType.DateTime and not SqlDbType.DateTime2 so the precision is being lost when writing your date to the database.
Explicitly setting the type to datetime2 will solve the issue. For example:
command.Parameters.AddWithValue("#now", DateTime.Now).SqlDbType =
SqlDbType.DateTime2;
Edit
#marc_s makes a good point with his comment:
You should read (and embrace!) Can we stop using AddWithValue() already?
To avoid these kind of issues from biting you, you could get into the habit of using the Add method on the parameters collection which takes the SqlDbType in some overloads and then set the Value property on that rather than using the AddWithValue method:
command.Parameters.Add("#now", SqlDbType.DateTime2).Value = DateTime.Now;
Maybe your database field is not storing your entire DateTime.Now value, because it's not precise enough. Why don't you simply compare your dates after you've formatted them as you like?
eg: (untested):
var databaseDate = d1.ToString("MM/dd/yyyy HH:mm:ss.fff");
var tempDate = d2.ToString("MM/dd/yyyy HH:mm:ss.fff");
Assert.AreEqual(databaseDate, tempDate);
I tested: using Linq To Entities My DateTime.Now is correctly saved to my datetime2(7) and equality test return True.
Are you sure you're passing your correct datetime value to the database? without truncating it?

sqldate time overflow in ASP.NET using VB.NET

I've been through a tough day facing this problem. In ent object, I have DiinputTanggal property as Date. In database, I have DiinputTanggal column as DateTime. When I try to insert the ent object into the database, I got the following error shown in the screenshot below. But when I debug, the property DiinputTanggal in ent object seems perfectly fine and nicely formatted. I have no idea where is my mistake.
Looking at your screenshot, it is probably the TaggalAktif property which is causing the overflow. .Net DateTimes default to DateTime.MinValue which cannot be represented in SQL DateTime.
You have several options
Initialize the DateTime to a value supported by Sql DateTime (in the range indicated by the error)
Change the DateTime to be nullable in both the class and database, (and ensure the property is initialized to null).
Use another Sql DataType to store the data e.g. DateTime2 or just Date if time isn't needed.

SqlDateTime overflow, but I want a NULL or MinValue

On this project, I am tracking when something is created, edited, and finally processed. I have three DateTime fields setup for this. The code below is for when I create the record.
newsArchive.CreateDateTime = DateTime.Now;
newsArchive.ModifyDateTime = DateTime.MinValue;
newsArchive.SendDateTime = DateTime.MinValue;
naRepository.Add(newsArchive);
naRepository.Save();
I am getting "SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM." when I try to add it. I know I can't send a NULL. How would you handle this?
I am using Linq2SQL to process this.
Why can't you send a null? AFAIK, Linq2SQL supports nullable value types; you just need the column in the DB to be nullable or L2S won't project the DAO with the nullable type.
You could use (DateTime)(SqlDateTime.MinValue) instead of DateTime.MinValue. This will use the minimum SQL-compatible datetime value, explicitly cast to DateTime.
Though both SqlDateTime and DateTime actually store time as a UInt64 "Ticks" value, the difference between the two types is that SQL Server uses a different epoch (value for zero) and a different resolution (what 1 "tick" represents in fractions of a second) than the CLR's DateTime.
Which version of SQL Server are you using? If you are using SQL 2008 (or 2008 R2) you can use the datetime2 data type which can support the full range of the .NET DateTime type.
Otherwise, use NULL (your model will need to have a property of type Nullable<DateTime>) or live within the limitations of the data type and DateTime.MinValue exceeds the limit of the SQL datetime type.
Create your own minimum date - a Date variable with value 1/1/1753 12:00:00 AM and use that instead of DateTime.MinValue
The datetime2 datatype allows dates as early as year 1. You can also use DateTime? to allow null dates in your .net code

1/1/0001 12:00:00 AM not Updating SQL 2008 Date field

this is just weird and is giving me a headache. I looked over my code and I don't see any logical errors causing it.
Any other date set to my birthDate DateTime variable in my class works when I add it as the value in my conn.AddParam, but when I send back 1/1/0001 12:00:00 AM (which was sent by setting it to MinValue) to SQL 2008's Date field, it remains the default which I have set to null in the databse for that field:
conn.AddParam("#birthDate", birthDate);
birthDate is type DateTime. It's set to DateTime.MinValue; I don't see why it wouldn't take this.
I may not be understanding the question, but I believe January 1, 1753 is the earliest date supported by SQL Server.
Source
If you need to go back that far, use DateTime2. It allows you to go back as far as 1/1/0001 http://technet.microsoft.com/en-us/library/bb677335.aspx
Just a guess but it might be caused by a casting issue. Since your birthDate variable has a time component (12:00 AM), SQL might be casting it to a DateTime before its inserted into the Date field. Since 1/1/0001 is an invalid SQL DateTime it might be having problems. Try setting your #birthDate parameter to birthDate.Date instead.
In SQL server 2008 :
Date data type : - will allow you to store only date (YYYY-MM-DD) and as range 0001-01-01 through 9999-12-31.Its accurate to 1 day
Time data type : It stores in the format hh:mm:ss:nnnnnnn , with range 00:00:00.0000000 through 23:59:59:9999999 and is accurate to 100 nanoseconds
DateTime2 : the format is YYYY-MM_DD hh:mm:ss:nnnnnnnm with a range 0001-01-01 00:00:00.0000000 through 999-12-31:59 9999999,accuracy is 100 nano seconds
DateTimeOffset:It includes additional information to track the time zone.The format is YYYY-MM-DD hh:mm:ss[.nnnnnnn][+/-]hh:mm with a range of 0001-01-01 00:00:00.000000 through 9999-12-31 23:59:50.9999999.storage 8 yo 10 bytes.
DateTime is a value type. Therefore if a DateTime variable hasn't been assigned it's value would be the default one which happens to be DateTime.MinValue. That's why when you explicitly set your birthDate to DateTime.MinValue it's treated as it was not assigned at all (e.g. as null) and thus gets replaced by the default value for that parameter in your stored proc.

Categories

Resources