Equality comparison fails between C# datetime and SQL datetime - c#

I am trying to do an equality comparison between a C# datetime and a SQL datetime, which appears to fail due to the precision in which those values are stored.
So say I have a really simple SQL table, with these fields:
ID (PK, int, not null) - identity
Title (text, null)
UpdateTime (datetime, not null)
I create a class object via Entity framework, setting its UpdateTime to DateTime.Now like so:
DateTime now = DateTime.Now;
Title.UpdateTime = now;
When I insert my new object into the table, I see that all the values appear to be stored correctly. Now I want the ID that was created for my object.
This is where things get borked. I try pulling the ID back via LINQ:
Title.ID = context.DBTitles.Where(x=>x.UpdateTime == now).FirstOrDefault().ID;
This throws an exception because the query returns null, despite the fact that the 'now' I've inserted is supposedly the same as the 'now' that was inserted into my table.
So my question : How do I ensure that my C# datetime is equivalent to the datetime stored in SQL? What is the best way to get my ID back?

If you are using SQL server, use DateTime2 instead. It has the same precision as the .NET type.

If you're using Linq, won't the object you're inserting get the ID assigned to it upon commit? You won't need to 'recall' it.

Related

SQL DateTime Vs. C# Datetime MinDate

I have a SQL Server database, one of my tables LatestData has a column which is a non-nullable DATETIME, with a default value of 01/01/1970. See code below the the exact T-SQL code for this column.
[MyDateTime] DATETIME DEFAULT (CONVERT([DATETIME], CONVERT([DATE], '1970/01/01 00:00AM', (0)), (0))) NOT NULL
When this table is added into our server code (C#) via an .EDMX data model, the field looks like the following:
public System.DateTime MyDateTime { get; set; }
I add new data to this table through C#, but at the time of adding the row, my MyDateTime column does not have any data.
As the column is Not Null, my MyDateTime field is set to 01/01/0001 automatically.
Trying to add this date to my DateTime column throws the following error:
System.Data.SqlClient.SqlException: The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.
After doing some research I found that C# Datetime MinDate is 01/01/0001, whereas SQL Server DATETIME's mindate is 01/01/1753 and this is causing the error.
The C# code is passing the 'empty' field as 01/01/0001 to the database which is then trying to convert it. This is obviously unsuccessful.
Is there any way for the database to know to revert to the default value instead of trying to convert the DATETIME firstly, or do so if a conversion fails?
I know that I could set the column in the Datatable to be a DateTime2 or specify a date for this column before adding it via C#, but that doesn't seem like the best way to go about it?
Thanks in advance for any help.
If 1970-01-01 is an acceptable no date set to you, then put it in the C#:
public System.DateTime MyDateTime { get; set; } = new DateTime(1970, 1, 1);
I do think you should consider allowing nulls in the column though, and make it:
public System.DateTime? MyDateTime { get; set; }
You asked for a SQLS-only fix; the only one I can think of right now is to use a stored procedure to do your insert:
--set up an example table with a datetime
create table a(a datetime);
--test that an insert doesnt work out
insert into a(a) values(cast('0001-01-01' as datetime2)); --error!
go
--make a procedure to do the insert logic/conversion
CREATE PROCEDURE a_ins(#a DATETIME2)
AS
BEGIN
INSERT INTO a (a)
--if the date is less than the column will support, default it
SELECT case when #a < CAST('1753-01-01' as datetime2) THEN cast('1970-01-01' as datetime) else cast(#a as datetime) end
END
GO
--quick run the procedure to test
DECLARE #dt2 DATETIME2 = cast('0001-01-01' as datetime2);
EXEC a_ins #dt2 --inserts 1970
You ca choose what range of dates you want to insert - maybe anything before 1970 will become 1970, maybe anything before 1753, maybe only 0001-01-01 .. you choose in the "case when" logic
This is yet another reason why you should prefer DateTime2 over DateTime - The DateTime2 data type supports the same date range as the .Net framework's DateTime struct - from January 1st 0001 to December 31 9999.
Change the MyDateTime data type to DateTime2, and the default value to 0001-01-01:
ALTER TABLE MyTable
ALTER COLUMN MyDateTime DateTime2 NOT NULL
To change the default value constraint you need drop it and re-create it.
This can be easily done using SSMS (just find it, right-click and drop) but using T-SQL you will have use one of the answers from this post since you didn't specify it's name. Once you've done that, you can add it (with a proper name this time):
ALTER TABLE MyTable
ADD CONSTRAINT DF_MyDateTime DEFAULT ('0001-01-01') FOR MyDateTime

.Net DateTime cannot be saved to SQL Server DATETIME because of precision

I have a property on an class that is of the .Net type DateTime. It is attempting to save into a table in SQL Server 2008 with a type of DATETIME. I am receiving a Database Error when I attempt to save a new record to the table from my .Net service.
When I look at SQL Server Profiler and see the call to the Stored Procedure that saves to the table, the property is a string: '2014-09-04 23:08:18.0500000'. When I truncate this string to just milliseconds the Stored Procedure call succeeds. The conversion of my .Net DateTime property to this string all happens under the hood and I have no control over that.
I do not need the full precision that I am seeing in the string, but it is important to keep milliseconds. I would rather not change my table column to a data type of DATETIME2. How can I remove the extra precision from the .Net DateTime property?
DateTime dateTime;
dateTime.ToString("yyyy-MM-dd HH:mm:ss.fff");
Please have #Tanner reply and mark that as an answer if correct as I believe he is correct in his comment above. Be careful to check for NULL on DateTime as you cannot convert to formated string if no data exists.
Below explains the range of DATETIME field in SQL Server.
http://msdn.microsoft.com/en-us/library/ms187819.aspx

How to make a database consult using a date and time variable?

I have the following line code used to retrieve data from database:
DataTable newEquipmentTable = database.Connection.RetrieveData(database.AdapterType, string.Format("SELECT ID FROM Equipment WHERE Name = '{0}' AND CreatedOn = '{1}'", equipment.Name, equipment.CreatedOn.ToString("yyyy-MM-dd HH:mm:ss.fff")));
It returns an error saying "The conversion of varchar data type to a datetime datatype resulted in an out-of-range value"
When I make a direct consult, using the following query it returns the expected result.
SELECT ID FROM Equipment WHERE Name = 'aa' AND CreatedOn = '2012-04-17 19:42:49.650'
What am I doing wrong?
You're passing a String value to select a datetime field. So you need to convert it to a datetime first:
Convert(datetime,'2012-04-17 19:42:49.650', 102)
Apart from that you might be open for SQL-Injection as #Mr47 has mentioned, use SqlParameters.
Please note that SQL's datetime type cannot hold values prior to 1753-01-01.
Just inspect the SQL string with the debugger before it is used to query the database in order to find the problem.
However, the best thing to do is to use a parameterized query (like in this example); otherwise you're vulnerable to SQL Injection.
What is the value of equipment.CreatedOn?
I think problem with the culture setting either in sql-server or your application. It cannot directly covert your date. User culture setting will solve problem.

How to convert SQL Server timestamp object to string

I need your help in small problem, I have a column (data type timestamp) in SQL Server 2008.
Now I want to show this timestamp value in ASP.Net C# app as string. Is there any way to do that?
I tried it using regular data fetching in ASP.Net but it produced System.byte[] as output rather than actual value. In SQL Server Management Studio values are represented as 0x000000000000B3C0.
One option is to change it to the Date, while getting from the database. Like:
SELECT timestamp = DATEDIFF(s, '19700101', yourTimestampColumn)
FROM yourTable
I don't know if i catch you, but in sql you can cast timestamp value to datetime then to varchar like this:
declare #val timestamp = 0x0000AAE200B29565
select cast(cast(#val as datetime) as varchar(max))

Getting DB Server DateTime in application

I am using Entity framework and have 1 field in database AddedDate that is DateTime and not null, so I need to pass DateTime value.
But the problem is I have to pass DB Server datetime. How can I manage in this sceario or how can I get DB Server datatime to pass this.
I need to some unique solution, because I am this on many forms.
Edit: I need DB server Datetime upon insertion/updation in my application so that I can pass to entity framework object.
Thanks
Since you are using entity framework, you can do something like this:
var dateQuery = yourDbContext.CreateQuery<DateTime>("CurrentDateTime() ");
DateTime dateFromSql = dateQuery .AsEnumerable().First();
In general, if you use the entity framework and you use DateTime in a field, it will automatically do the back/forth conversion for you, just the same way it does so for integers, doubles etc.
Unless you mean something special, i.e., a char[40] field that must be filled with a DateTime value of a particular format.
You can get database server date and time by running SELECT GETDATE()) script.
Consider you have a table with 4 colums - the first 3 being strings and the last datetime, You can solve your issue by issueing INSERT SQL like this:
INSERT INTO myTable VALUES ('x', 'y', 'z', SELECT GETDATE())
Can't you use a stored procedure so you can get DB server Datetime very easily.
Just use getdate() in your query. For example:
INSERT INTO your_table (AddedDate, ...other columns) VALUES (getdate(), ...other values)
This basically asks the server to insert its own current date into the field; there's no need for you to retrieve it locally.

Categories

Resources