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?
Related
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.
How to retrieve Timestamp value(eg:0x000000048E18B9D8 ) from SQL Server using DataReader? I'm getting an IndexOutOfRangeException when doing like this
DateTime date = reader.GetDateTime(reader.GetOrdinal("Timestamp"));
Can anyone help on this?
Also I want to know how to pass timestamp parameter to stored procedure using .Net code
IndexOutOfRangeException thrown on reader.Getordinal() suggests that a column called Timestamp doesn't exist. Check your column names again, and replace with the actual value. By default, it will be called timestamp, but only if you haven't specified a column name.
You could also try string ts = reader["timestamp"].toString(), and make sure it returns something.
According to MSDN, a TIMESTAMP data type is "8 bytes...[and]... just an incrementing number and does not preserve a date or a time. To record a date or time, use a datetime data type."
Therefore, reader.GetInt64() is probably close, if you really need this value, but byte[] myTimestamp = reader["timestamp"] is probably better.
As far as passing it back to your stored procedure, you can create a new parameter with SqlDbType.Timestamp. The value will be a byte array, or, if you have it stored as a string, you could try something like:
cmd.Parameters.Add("#TimeStampParam", SqlDbType.Timestamp).Value = System.Text.Encoding.ASCII.GetBytes(myTimestampStr);`
(NB: I haven't tested this, but it should be close enough).
Note that TIMESTAMP is deprecated, and ROWVERSION is not the preferred syntax.
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.
I have the following c#/Query:
TrackDuration =TimeSpan.Parse( Request.Form["TrackDuration"].ToString());
string InsertQuery = string.Format("UPDATE tblTracks SET TrackLength={0}, TrackDuration='{1}', TrackName='{2}',TrackDescription='{3}',TrackMap='{4}',DifficultLevel={5},OverallHeight={6},IsCircular='{7}', ForBeginners='{8}',StartPoint='{9}',ParkingPlace='{10}',SeasonOfYear={11},TrackLocation={12}, Images='{13}' WHERE UserID={14}",
TrackLength, TrackDuration, TrackName, TrackDescription, TrackMap, DifficultID, OverallHeight, IsCircular, ForBeginners, StartPoint, ParkingPlace, SeasonID, AreaID, ImageList, UserID);
But I got this error message:
Syntax error in UPDATE statement
Syntax error (missing operator) in query expression
I realy tried to solve this, but I can't.
How can I fix this problem?
Update:
This is the value of the Query:
UPDATE tblTracks SET TrackLength=35, TrackDuration='02:30:00', TrackName='45',TrackDescription='<p>sometext.</p>
',TrackMap='f',DifficultLevel=3,OverallHeight=450,IsCircular='true', ForBeginners='false',StartPoint='<p>קיבוץיסעור </p>
',ParkingPlace='<p>כניסה לקיבוץ יסעור</p>
',SeasonOfYear=1,TrackLocation=3, Images='' WHERE UserID=1
The sql values types are:
TrackLength = number ; TrackDuration = date/time ; TrackName= string ;TrackDescription= string; TrackMap = string; DifficultLevel=number;OverallHeight=number;IsCircular=true/false;ForBeginners=true/false;
StartPoint=string; ParkingPlace=string; SeasonOfYear=number; TrackLocation=number;Images=string
'02:30:00' is not a correct value for datetime DB field, AFAIK. The default format is controlled by date format setting.
Additionally, '20130412' should work in any case, but for datetime field. You need to format the TrackDuration correctly or use CAST/CONVERT. As TimeSpan doesn't contain date part (it represents a duration and not a point in time), you can only make it up (e.g. prepend "20100101") but that is an awful hack.
The proper solution is to use the correct DB field type.
'02:30:00' might work if the field was of time type. Please read some more about time types in SQL Server.
Even better, why don't you use plain integer for the duration in seconds? The duration is not a date anyway.
The much bigger issue is that you are concatenating strings to set the command text, which opens you for SQL injection attack. If I name the racing track a';DROP TABLE tblTracks;-- your database is toast:
UPDATE tblTracks SET TrackLength=35,
TrackDuration='02:30:00',
TrackName='a';DROP TABLE tblTracks;-- ...
I am working on c# project and using winform.
Here the problem is the query was working previously but now it is not working
Here the todaydate is a datetimePicker which is set to short date format
and my datatype of column is smalldatetime the error i am getting is
The conversion of a nvarchar data type to a
smalldatetime data type resulted in an out-of-range value.
The statement has been terminated.
if i have two date time picker one for date and second for time then how can i insert? please can you guide me
AddWithValue determines the datatype of the parameter from the value you pass.
In your case you are passing a string and thus the parameter is passed to the database as a string not as a datetime expected by the database
you should change that line
cmd.Parameters.AddWithValue("#today", todaydate.Value);
You're currently passing in the text value, which means something else is having to then parse it as a date. Don't do that. Given that you've got a DateTimePicker, you should just use the DateTime value it provides:
cmd.Parameters.AddWithValue("#today", todaydate.Value);
... or create the parameter first with a specific type (SqlDbType.SmallDateTime), then set the value using todaydate.Value. The important point is to avoid the string conversion.
Wherever possible, you should avoid converting values into text. Keep them in their "natural" form (e.g. DateTime in this case) for as much of the time as possible: on input, parse into the natural form, and if you can avoid ever converting to a string, do so!
I think your time7 column in database is smalldatetime and you tried to assign it a string. I don't suggest it.
Try with Add() method like this;
command.Parameters.Add("#today", SqlDbType.SmallDatetime);
command.Parameters["#today"].Value = todaydate.Value;
or you can use AddWithValue() as also like this;
cmd.Parameters.AddWithValue("#today", todaydate.Value);