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
Related
below is my code snippet where I insert a DateTime value to SQL database and encountered the following error:
System.Data.SqlTypes.SqlTypeException: SqlDateTime overflow. Must be
between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM.
deliveryCart.DeliveryDate = (DateTime)row.DeliveryDate;
Log.SaveLog(ConfigurationManager.AppSettings["LogFilePath"] + #"\Log.txt", "deliveryCart.DeliveryDate: " + deliveryCart.DeliveryDate.ToString());
//*value retrieved is 12/31/2019 12:00:00 AM
dataContext.Q_TBL_SUBMITTED_DELIVERY_CARTs.InsertOnSubmit(deliveryCart);
May I know if there is a format to be used? when converting the value of row.DeliveryDate?
actually the problem is SQL DateTime =/= C# Datetime
you need to change 2 things
Database change the field type from DateTime to DateTime2
Query you need to be explicit
you can find futher informations here,here and here
If you are using dateTime.toString(), then need to ensure that the string is formatted per:
deliveryCart.DeliveryDate.ToString("yyyy-MM-ddTHH:mm:ss.fffffff");
Also, DateTime is a value type and not a reference type. So, it cant be null. Value types if not initialised have a value of 0. For Datetime, it can be DateTime.MinValue which is outside Sql Server's value.
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.
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?
I'm using ado.net entity data model. When update entity object, this error shown "String or binary data would be truncated" or "SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM.". I know why this error shown.
How to handle this error created on which column ?
You probably have an uninitialized DateTime property on your object. The default value, which is in the year 0, cannot be stored in SQL Server's weirdly limited DATETIME columns. Set the property to a reasonable value or make it nullable in your DB.
In addition to Craig you could set both - the db-field and the variable - to nullable. Might be a bit more performant.
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.