SQL DateTime Vs. C# Datetime MinDate - c#

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

Related

How to save date different format to SQL Server

I'm trying to save date in yyyy-mm-dd format instead of yyyy-dd-mm format to my database. I added
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
to the model class, but result didn't change. Date is still yyyy-dd-mm format in database.
Is it necessary doing it with C# code I can't change anything in database table. How can I do that ?
Dates in a (relational) database should be stored in a datetime column, or the equivalent for whatever flavour of database you are using (SQL server documentation). You can choose any format to display the date in your application, that has no bearing on how is stored.
If you're storing the dates in a database in a text format, you are storing up a world of pain that will come back to hurt you later on.
If your column is a string column, you should change it and use a date column as MarcE mentionned.
But, according what I understood, you have a Date column and you want to change the format.
In sql server date is not store like a string.
And the format that you see is associated the collation of your database.
If you want to change it, you should try to change date format of your db.
-- Set date format to day/month/year.
SET DATEFORMAT dmy;
GO
DECLARE #datevar datetime2 = '31/12/2008 09:01:01.1234567';
SELECT #datevar;
GO
-- Result: 2008-12-31 09:01:01.123
SET DATEFORMAT dmy;
GO
DECLARE #datevar datetime2 = '12/31/2008 09:01:01.1234567';
SELECT #datevar;
GO
-- Result: Msg 241: Conversion failed when converting date and/or time -- from
character string.
GO
https://learn.microsoft.com/en-us/sql/t-sql/statements/set-dateformat-transact-sql?view=sql-server-ver15

How can I store only the date portion of the datetime. Today property to a SQL Server table datetime column?

I am trying to update a datetime column in a SQL Server 2012 table by using
newItem.DateSaved = DateTime.Today;
I want to save only the Date part of DateTime, but when I am checking in the table I can see that it saves also the time part: 2018-07-27 00:00:00.000 .
How I can make it to store only date part? 2018-07-27 ?
Edit
Because my column is datetime, I see that I can't store only the date part. But how I can show to the user only the date part without time? Here is the select part of the Linq-to-SQL query:
select new { Date = smv.DateSaved.Value.Date }).Distinct();
A datetime column always has a time part - just, in your case it will all be zeros. A datatime is just a number under the hood; it doesn't have any choice about what it has / doesn't have; similarly, it doesn't have any notion of formatting until your code tries to display it, and then it is the dispalying code that chooses the format.
If you don't want a time part, use date instead of datetime for your column.
Change column type in SQL Server from datetime to date (https://learn.microsoft.com/en-us/sql/t-sql/data-types/date-transact-sql?view=sql-server-2017)
If you want to store only the date without time in SQL Server database you can set the column type to date
ALTER TABLE table_name
ALTER COLUMN DateSaved date;
Reference: https://learn.microsoft.com/en-us/sql/t-sql/data-types/date-transact-sql?view=sql-server-2017
If you have a DateTime property in your model and you want to show only the date part just format it in your control in the View. For example:
$"{newItem.DateSaved:yyyy-MM-dd}"
or
newItem.DateSaved.ToString("yyyy-MM-dd")
You can also use "d" or "D" (short and long version) instead of specific format like "yyyy-MM-dd" if you want to have default formatting.
If your view is written in HTML or XAML do it there using the same formatting technique.
It is because your field on the database is DateTime. If you want to store just date, you should have a field with date data type. In this link, you can see the difference between the date data types.

How do I automatically get date when I create a new row in my SQL table?

I am doing a project in school, I have to create a website tool for salesmen to fill what they have done during the day, i.e. amount of quotes, quote sum, orders, order sum etc. I am using Visual Studio 2010, ASP.NET with C# with a SQL database.
I have to create a table with different columns, that I know how. But what I need is to have a column called Date and it has the datatype date. I need it to be filled automatically without having to input it manually. The same date that the new information was added. I have searched for solution in google and other places but I think I am searching with the wrong keywords, hopefully you can help me.
The format I wish for the date to be is DD-MM-YYYY
When you look for SQL default date on Google, the second result you get is this one.
In there, you have a default date example:
CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
OrderDate date DEFAULT GETDATE()
)
using the DEFAULT keyword.
Create a sql datetime column in the database, and specify a default value of GetDate() or GetUtcDate() depending on which you want. Format is irrelevant on the input side; you will have to use a formatter on the select side (or in your c# code).
You can set the default value for the column as current date time..
create table tblname (
fieldname datetime default getdate()
)
Also see this question
Add default value of datetime field in SQL Server to a timestamp
You can use one of this to insert in the table instead.
String s = System.DateTime.Now.ToString("dd.MM.yyyy");
DateTime now = System.DateTime.Now;
The second one would be your choice because the type specified in yur table is Date.
If don't want to be setting it from the app, specify which database you are using to get a specific answer.

Pass a NULL value to DateTime Field in LINQ

My database table is like this
CREATE TABLE MYBUDGET.tbl_CurrentProperty
(
[PropID] INT NOT NULL IDENTITY(1,1),
[UpdatedOn] DATETIME NOT NULL,
[Amount] MONEY NOT NULL,
[Remarks] VARCHAR(100) NOT NULL,
)
ALTER TABLE MYBUDGET.tbl_CurrentProperty ADD CONSTRAINT PK_CurrentProperty_PropID PRIMARY KEY ([PropID])
ALTER TABLE MYBUDGET.tbl_CurrentProperty ADD CONSTRAINT DF_CurrentProperty_UpdatedOn DEFAULT (DATEADD(MINUTE,30,DATEADD(HOUR, 5, GETUTCDATE()))) FOR [UpdatedOn]
ALTER TABLE MYBUDGET.tbl_CurrentProperty ADD CONSTRAINT CK_CurrentProperty_Amount CHECK([Amount] > -1)
GO
I'm using LINQ to SQL. In C# I need to pass only [Amount] and [Remarks] fields and other fields must be used with their default values ([PropID] and [UpdatedOn]).
In C# I create tbl_CurrentProperties object like below,
tbl_CurrentProperties currentProperties = new tbl_CurrentProperties();
currentProperties.Amount = 50.00M;
currentProperties.Remarks = "remarks";
and then submit the object to the data context. But here, Linq assigned '1/1/0001 12:00:00 AM' for UpdatedOn field. But this violate the SQL datetime range 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM and Occurring an exception. Also I can't assign a NULL value manually for a DateTime field since its a not nullable type. Anyhow I need to make this to use its DEFAULT Constraint. How do I do this?
PS: I want to use it like this because, My database is Online and Users are in different locations. So If I used DateTime.Now, the time in the user machine may be wrong, and It insert a wrong value into DB. I need to use SQL server time always.
Andrey's answer is partly right. I just tested this and here's what I found.
In your dbml designer, on your UpdatedOn column set the following:
Auto Generated Value = True
Nullable = False
Then, on an INSERT if you use SQL Server Profiler to look at the generated SQL, you'll see that UpdatedOn is not included in the INSERT. Not even a null value. This is important: for SQL Server to use a default value for that colum, the column must be omitted from the INSERT. If you set Nullable = True on the UpdatedOn, LINQ to SQL might be including the column on the INSERT with a null value.
FYI, immediately after the INSERT there should be a SELECT where LINQ to SQL is retrieving the auto-generated value, so your entity object has the latest value.
I recommend you open your DBML file using XML Editor and change that column's type from DateTime to DateTime? by allowing nulls. Save it and the code will be generated for you.
Whenever LINQ to SQL generates wrong DBML, it is better to edit it yourself.
Open your dbml and turn on
"Auto Generated Value" = true for the fields that are auto generated. You should be all good with passing nulls in

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