DateTime sent in wrong format to Sql Server 2014 - c#

I'd like to execute a stored procedure on an sql server 2014. The sql server is set up in German, the user used for connecting to the sql server has also configured German as language. If I try to execute the sql procedure or raw sql, I always get the error
varchar cannot be converted to datetime
even if I provide german datetime values. I've found out that it works if I prepend the sql text with the command SET DATEFORMAT dmy.
The problem is the same for ADO .NET as well as Entity framework. Setting the thread and ui culture to German also didn't help.
It seems that C# SQL Connection sets the culture to default (English) independently of thread culture, date format or sql server language.
Any ideas highly appreciated how to set the culture correctly - such that I don't need to send always SET DATEFORMAT dmy before the real sql text.
UPDATE
This is my code to call the sql stored procedure and pass the dates using the c# sql parameter.
SqlConnection sqlConnection = null;
try
{
// open connection to the database
sqlConnection = new SqlConnection(Convert.ToString(ConfigurationManager.ConnectionStrings[ProductivityAnalyzerDatabase.ConnectionStringName]));
sqlConnection.Open();
// setup command
var sqlCommand = new SqlCommand("UpdateEmployeeBalances", sqlConnection);
sqlCommand.CommandType = CommandType.StoredProcedure;
sqlCommand.Parameters.Add(new SqlParameter("#employeeId", employeeId));
sqlCommand.Parameters.Add(new SqlParameter("#startDate", startDate));
sqlCommand.Parameters.Add(new SqlParameter("#endDate", endDate));
sqlCommand.ExecuteNonQuery();
}
finally
{
if (sqlConnection != null && sqlConnection.State == ConnectionState.Open)
{
sqlConnection.Close();
}
}

Date values are not stored with their display format.
The problem is that you send your dates to Sql Server as strings, thus forcing sql server to cast the strings to date values. unless you send your dates in ANSI-SQL format (yyyy-mm-dd) this casting might fail or yield unexpected results (is 04/02/2015 April 2nd or February 4th?)
The correct solution, as Steve mentioned in his comment, is to use c#'s DateTime structure as the value of the parameter for the stored procedure. (don't use ToString or anything like that.)
Note that the parameter should be declared as a date type (datetime, datetime2, or date) in the stored procedure itself.

Good day,
You can read more about this issue in this clog:
http://ariely.info/Blog/tabid/83/EntryId/161/Date-displaying-format-vs-Date-storing-format.aspx
in short (from the link above):
Implicit conversion of ambiguous date formats are interpreted according to the language of the connection or the collate of the query. Always keep and following rules, in order to make your work more compatible.
Using .Net you should use a type that is mapped correctly to the SQL Server types. Check this link: https://msdn.microsoft.com/en-us/library/cc716729%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
When you specify dates in DML queries, always use constants way that
are interpreted the same way for all language settings!
for example use format yyyymmdd as 20160227, Use explicit CONVERT statement with an explicit style parameter, Use escape clauses while using ADO, OLE DB, or ODBC.
Remember that those are only display formats. In the database the
data stored in the same way, no matter what is your language!
*datetime is stored as 4 bytes for the date + 4 bytes for the time, Datetime2 is a bit more complex since it is flexible. you can read more on the undocumented internal stored format here.
I hope this is useful :-)

Related

C# PostgreSQL date format exception

I have format exception when i trying to add '9/30/2019 5:15:54 PM'(DD-MM-YYYY) to my database.
I'm already SET datestyle = 'ISO, DMY'. So now i can use it like:
INSERT INTO products(name, createdat) values ('test', '9/30/2019 5:15:54 PM')
I have the same SQL command in C# and PostgreSQL, but it works only in Postgre-pgAdmin(nice joke C#).
How can fix this error in C#?
Well if you insert a valid Postgres timestamp literal, it should work everywhere:
INSERT INTO products (name, createdat)
VALUES
('test', '2019-09-30 17:15:54'::timestamp);
Perhaps the setting you configured were only valid from the session originating from pgAdmin, but not with the Postgres driver which C# is using. In any case, the default Postgres timestamp literal is ISO compliant (your version is not), which is always a good thing.

How to save c# (asp.net core) datetime to PostgreSQL date

I am using the npgsql package to pass parameters to a postgresql function. But I am getting exception saying that a function with the specified number/type of arguments is not defined. I went throught the trouble of testing all the parameters and I am sure the one that is causing the problem is the c# datetime parameters that is passed to a postgresql date data type.
I orginally tried this:
//here BirthDate is Datetime, as it doesn't seem
// to have another built-in date type in asp.net core
cmd.Parameters.AddWithValue("#birth_date", cliente.BirthDate);
I read some post here in SO and they said that using the property Date would solve but it didn't work for me.
//doesn't work either
cmd.Parameters.AddWithValue("#birth_date", cliente.BirthDate.Date);
NpgSql's AddWithValue does its best to map the datatype of the C# property to the PostgreSQL field's datatype, but the issue is that PostgreSQL has two primary datatypes for date:
date
timestamp
But C# has just the one -- System.DateTime. So even the .Date Property of a DateTime object yields a DateTime type.
In other words, NpgSql has to make a choice -- and it renders the PostgreSQL datatype as a timestamp. If your DB type is actually a date, the execution will fail due to datatype mismatch.
For strings, integers, decimals and doubles AddWithValue always seems to work exactly as expected, but if your date is a [PostgreSQL] DATE then you need to be explicit with your parameter declaration's datatype. In general, this is a good practice anyway:
cmd.Parameters.Add(new NpgsqlParameter("#birth_date", NpgsqlTypes.NpgsqlDbType.Date));
cmd.Parameters[0].Value = cliente.BirthDate;
This is definitely advantageous over AddWithValue if you are doing multiple transactions like this:
cmd.Parameters.Add(new NpgsqlParameter("#birth_date", NpgsqlTypes.NpgsqlDbType.Date));
cmd.Parameters.Add(new NpgsqlParameter("#user_id", NpgsqlTypes.NpgsqlDbType.Integer));
foreach (User u in Users)
{
cmd.Parameters[0].Value = u.Birthday;
cmd.Parameters[1].Value = u.UserId;
cmd.ExecuteNonQuery();
}
For a single query or transaction, you can also use the Shorthand:
cmd.Parameters.Add(new NpgsqlParameter("#birth_date", NpgsqlTypes.NpgsqlDbType.Date)).
Value = cliente.BirthDate;
As a final alternative, you can "fix" the dbtype after the fact:
cmd.Parameters.AddWithValue("#birth_date", cliente.BirthDate);
cmd.Parameters[0].NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Date;
I don't think that's any easier than the other options, but it is an option that will work.

DateTime sql server vs. System.DateTime

I have a stored procedure which input is from the type datetime. i.e. I transfer the input
2014-01-13T16:55:03.370 ,while running the stored procedure from the sql server.
Now I want to execute a stored procedure from the application.So I tried to use parameter having System.DateTime type.Looks like it is not corresponds to sql datetime.
Which type should I use for that?
UPD.
I didn`t get the answer for my question. So I`ll try to make my question more clear.
In SQL SErver database tables the values of the type datetime are saved.I am writing a stored procedure which looks for this values .I mean I need to get a parameter from the user of the for yyyy-mm-ddThh:mm:ss:.mmmm
from MSDN:
GetDate() is a inbuilt function in sql, for c# you can use follwing:
DateTime CurrentDate;
CurrentDate = Convert.ToDateTime(DateTime.Now.ToString("dd-MMM-yyyy"));
I guess you can pass this variable through to the procedure call parameters?
or, search the site again and read: Function that creates a timestamp in c#
Here you can find samples on data time conversions between SQL and C#, depending
on the date data types you use

Safe DateTime in a T-SQL INSERT statement

Been running in problem lately with using a DateTime in a T-SQL INSERT INTO statement. Work fine on one machine but might not work on another and I guess this has to do with locale settings.
So if I have DateTime variable what is the safe way of using that in a SqlStatement string that it will always work regardless on local system settings?
Thanks
Use parameterized INSERT query.
Most likely, your code is assembling the SQL command string. That also makes your code vulnerable to SQL Injection.
You should use parameterized query as Adrian suggested.
Another possibility is to use an ISO 8601 string representation like described here which is independent of locale settings.
That would look like:
20110921 15:20:00
Either you use parametrized command/stored procedures where you create a parameter of type DateTime in the stored and assign it from .net code when you call the stored (so .NET and SQL will know they are working with a datetime and will never confuse/swap day and month), or you include a specific command on top of your insert commands and then format all dataetime strings with this pattern, for example:
SET DATEFORMAT dmy;
SET DATEFORMAT (Transact-SQL)

How to insert date in an Oracle relational database using C#

I have Date Var in Oracle, and I try to insert Data from my C# program
sql = "insert into Table(MyDate) values (" + convert.todatetime(txt) + ")";
I get an Error, what can i do ?
cmd.CommandText = "INSERT INTO Table (myDate)VALUES(:dateParam)";
cmd.Parameters.Add(new OracleParameter("dateParam", OracleDbType.Date))
.Value = DateTime.Now;
cmd.ExecuteNonQuery();
Use parameters. It's going to solve your problem and prevent injection.
Oracle expects it to be an actual date value, not just a string that looks like a date. You have to use the TO_DATE() function to explain how your string is formatted, something like this:
INSERT INTO Table (myDate)
VALUES(TO_DATE('2009-03-30 12:30:00', 'YYYY-MM-DD HH:mi:ss'));
Try using DateTime.TryParse(text) or DateTime.Parse(text)
I know this was a poorly asked question, but I saw some poor answers when I had the same question and ran into this. This is how I solved it, and I'll answer using the OP's context:
Parse the date in to a DateTime variable:
DateTime myDate = DateTime.Parse(txt);
Then parameterize your query:
sql = "insert into Table(MyDate) values (:myDate)";
Set up an OracleParameter:
OracleParameter param = new OracleParameter();
param.ParameterName = "myDate";
param.OracleDbType = OracleDbType.Date;
param.Value = myDate;
Assuming you already have an OracleConnection as connection, set up your command and add your parameter:
OracleCommand cmd = new OracleCommand(sql, connection);
cmd.Parameters.Add(param);
Execute:
cmd.ExecuteNonQuery();
Do NOT waste your time on any of the TO_DATE nonsense. This is for when you are adding something using SQL*Plus or Oracle SQL Developer directly, or MAYBE where you want to send in a STRING variable's value (not a DateTime variable) in the EXACT format that TO_DATE expects and that you assign within the TO_DATE construct within your query or a stored procedure (i.e. to_date('2013-05-13 12:13:14', 'YYYY-MM-DD HH24:MI:SS'). Using a DateTime variable and assigning that to an OracleParameter with an OracleDbType of OracleDbType.Date, assuming you have a DATE field in your table and can parse txt into a DateTime variable, however, is best and easiest.
Easiest way possible:
DateTime inputDate = Convert.ToDateTime("01/01/2019"); //<---Input Sample Date in format
string queryParameters = String.Format("SELECT * FROM TABLE WHERE DATE = '{0}')", inputDate.ToString("dd-MMM-yyyy")); //<-- Converts System.DateTime into Oracle DateTime
//Forget looking anywhere else for an answer, copy and paste and reform this very code
//and see the results
Please bind your variables (like ocdecio tells) ! Not only does it prevent sql injection it is also much faster. Especially in a multi concurrency situation. Read for example here: http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28844/building_odp.htm#CEGCGDAB .
"Bind variables are placeholders inside a SQL statement. When a database receives a SQL statement, it determines if the statement has already been executed and stored in memory. If the statement does exist in memory, Oracle Database can reuse it and skip the task of parsing and optimizing the statement. Using bind variables makes the statement reusable with different input values. Using bind variables also improves query performance in the database, eliminates the need for special handling of literal quotation marks in the input, and protects against SQL injection attacks."

Categories

Resources