I am trying to pass date to a sql procedure, the time is being passed, and causing the proc to fail, because the times do not match, c# is passing date 12:00:00 database shows date 00:00:00
so here is my code
public class
datetime dt_value;
get the date from the javascript calendar
DT_Value = Convert.ToDateTime(Request.Form["TextBox_Tracking_ImportDate"]);
try to convert to mm/dd/yyyy
string DT_Value2 = DT_Value.ToString("ddMMyyyy");
pass date to sql
cmd.Parameters.Add(new SqlParameter("#import_date", DT_Value2));
ERROR: Error converting data type nvarchar to smalldatetime.
Just pass the DateTime directly..
cmd.Parameters.AddWithValue("#import_date", DT_Value);
See SQL Server Data Type Mappings
This is the first problem:
string DT_Value2 = DT_Value.ToString("ddMMyyyy");
cmd.Parameters.Add(new SqlParameter("#import_date", DT_Value2));
You're performing a pointless string conversion, and as a result you're corrupting the data. Just don't do it. Always avoid string conversions as far as you possibly can.
Pass the DateTime directly:
cmd.Parameters.Add(new SqlParameter("#import_date", DT_Value));
Or better, specify the type explicitly:
cmd.Parameters.Add("#import_date", SqlDbType.Date).Value = DT_Value;
Or to just take the date part explicitly from the DateTime:
cmd.Parameters.Add("#import_date", SqlDbType.Date).Value = DT_Value.Date;
To be honest though, if your SQL code actually knows that the parameter is a Date rather than a DateTime, there shouldn't even be the concept of a time part. If you could post your SQL, that would help us diagnose that aspect. It's really important to work out the right types to use - it makes life so much simpler.
Related
I have retrieved a date from an application and stored it in a DateTime Variable. The format of date is dd/mm/yyyy.
I now want to update a column (with datatype date (yyyy/mm/dd)) in a sql server 2008 database with this date
I have tried the below code, but it's giving me an exception "string was not recognized as valid datetime". Please help to solve this problem.
DateTime date = calExpirydate.SelectedDate;
DateTime date1 = DateTime.ParseExact(date.ToString(), "YYYY/MM/DD", CultureInfo.InvariantCulture);
You don't need to convert it at all if you use parameters (and you should be).
A rough example:
DateTime date = DateTime.Now;
SqlCommand command = new SqlCommand();
command.CommandText = "INSERT INTO table (date) VALUES (#date)";
command.Parameters.Add("#date",SqlDbType.DateTime).Value = date;
I'm using SQL Server here, however the concept is similar across most ADO.NET providers.
Your DateTime variable in the framework is stored in one basic format. The way it appears is just formatting off of the .ToString. It's saying give me your date bit make it look like this. Sql server is similar, it understands the date time variable regardless of how it appears.
If you pass your DateTime as exactly how it is in the framework it will save it correctly. The date and time isn't changing just how it's displayed. Your try parse isn't working though because it's not able to recognize the partial string you're giving it.
You don't even need a new date time variable to see it the way you want. Even if you're successful you will have identical date time variables.
yyyy/MM/dd should be correct
DateTime string format
so i have a string "09/15/2014" and in c# it converts it to date:
DateTime from = Convert.ToDateTime(fromdate);
this outputs "9/15/2014" and when I send it over to sql I get this:
select convert(varchar, '9/1/2014 12:00:00 AM', 101)
which doesn't work for me because I need to keep any leading zero's.
help?
If you're worried about the string formats for dates with Sql Server, you're doing it wrong. As a comment to another answer indicates, SQL Server internally stores all dates in a machine-optimized numeric format that is not easily human-readable. It only converts them to a human-understandable format for output in your developer tools.
When sending dates to Sql Server, always use query parameters. In fact, when sending any data, of any type, to Sql Server in an SQL statement, always use query parameters. Anything else will not only result in formatting issues like your problem here, but will also leave you crazy-vulnerable to sql injection attacks. If you find yourself using string manipulation to include data of any type into an SQL string from client code, step away from the keyboard and go ask a real programmer how to do it right. If that sounds insulting, it's because it's so hard to understate the importance of this issue and the need to take it seriously.
When retrieving dates from Sql Server, most of the time you should just select the datetime field. Let client code worry about how to format it. Do you want leading zeros? Great! The Sql Datetime column will at some point be available in C# as a .Net DateTime value, and you can use the DateTime's .ToString() method or other formatting option to convert the value to whatever you want, at the client.
SQL queries use a date and time format which goes like this:
2014-09-15
That's year-month-day. As per the comments below, this may be different depending on the collation you have on your database (see Scott's comment for a more accurate way to describe this and get dates into this format).
DateTime's ToString method has an overload which takes a formatting string. So you can pass the format you want the string to be output to. Try it like this:
string queryDate = from.ToString("yyyy-MM-dd");
And see what you get. Use that on your query.
But if you really want this done right, use parameters. Like:
SqlCommand command = new Command(connection, "SELECT * FROM foo WHERE someDate = #date");
command.Parameters.AddWithValue("#date", from);
// where "from" is your DateTime variable from the code you've shown.
This will save you the trouble of DateTime to String conversions.
I am inserting some values into db. In DB field received_date is type of datetime datatype I am using following code for inserting But it is showing some exception, I am unable to figure it out.
Exception:
The conversion of a varchar data type to a datetime data type
resulted in an out-of-range value.
SqlConnection con = new SqlConnection("data source=ATLBLRDP-19\\PRIME;database=arp;uid=sa;pwd=****;");
con.Open();
SqlCommand cmd_r = new SqlCommand();
cmd_r.Connection = con;
cmd_r.CommandType = CommandType.Text;
cmd_r.CommandText = "insert into raw_mails(received_date,sender,receiver,subject,body,has_parsed,has_attachments,created_by,created_on,mail_type) Values(#received_date,#sender,#receiver,#subject,#body,#has_parsed,#has_attachments,'" + DateTime.Now + "','" + DateTime.Now + "',#mail_type)";
cmd_r.Parameters.Add("#received_date", em.DateTimeReceived);
cmd_r.Parameters.Add("#sender", em.From);
cmd_r.Parameters.Add("#receiver", em.Receiver);
cmd_r.Parameters.Add("#subject", em.Subject);
cmd_r.Parameters.Add("#body", em.Body);
cmd_r.Parameters.Add("#has_parsed", 1);
cmd_r.Parameters.Add("#has_attachments", em.HasAttachments);
cmd_r.Parameters.Add("#mail_type", 4);
cmd_r.ExecuteNonQuery();
con.Close();
I checked with every query (parameters.add()) all are working but if I try to insert received_date then only it shows exception . Here em is type of EmailMessage.
And I am using sql server 2012 for DB purpose.
You don't give much to go on, but it is clear that you are setting a date value on your Sql server using a string.
There are definitely two and potentially three places you do this, depending on the type of em.DateTimeReceived. When you build your CommandText you also insert DateTime.Now twice, implicitly calling .ToString() for the conversion.
However, calling .ToString() will use your system's locale. For example, I am in the UK, so today's date (December 13) is written out as "13/12/2013 14:02:08". If I assign this string to a sql datetime it will fail, because my Sql server is using it's default US locale - so it reads 13 as the month and 12 as the day, and throws exactly the error you've seen.
So in order to fix this, you need to either:
output the dates as strings using an explicit format that matches your Sql server's collation (using DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss") or similar)
ensure that all of the dates passed in are actual DateTime variables and not strings, allowing the SqlCommand to ensure formatting is correct
The valid range for the datetime data type is 1753-01-01 through 9999-12-31 (Date and Time Data Types and Functions (technet))
If the em.DateTimeReceived property is smaller than 1753-01-01, you will get this error. Depending on data conversion from .NET to SQL, this might also be the case when DateTimeReceived is null.
Ensure that your property value is always greater than 1753-01-01 or use the datetime2 data type which has a range starting at 0001-01-01.
on a side note: Is there a specific reason you are still using the legacy datetime data type? Microsoft recommends "Use the time, date, datetime2 and datetimeoffset data types for new work. These types align with the SQL Standard. They are more portable. time, datetime2 and datetimeoffset provide more seconds precision. datetimeoffset provides time zone support for globally deployed applications." (msdn)
Either change the DateTime.Now to DateTime.Now.ToString("yyyy/MM/dd HH:mm") or pass them as parameters, similar to your other values.
I have this C# code:
string RegisterDate = DateTime.Now.ToString();
RegisterDate = RegisterDate.Remove(10);
RegisterDate = RegisterDate.Replace('/', '-');
RegisterDate = String.Join("-", RegisterDate.Split('-').Reverse());
Which gives thie result: 01-06-2013
The problem is that when I try to insert it to the table I get this result: 21/06/1894
When I get the date via input it works great in the same date format, so why in this case it doesn't work?
update
If I try this:
var RegisterDate = DateTime.Today.Date;
I get Error :
Syntax error (missing operator) in query expression
Wish for help, thanks!
Don't use a string conversion at all. Assuming your data type in the database is DateTime or something similar, just use a parameter and specify its value as the DateTime in your C# code to start with. (I'm assuming you're already using parameterized SQL rather than embedding data straight in your SQL. If you're not using parameters yet, start right away!)
I'd suggest using DateTime.Today to make it clearer that you're only interested in the date part. (Note that this means that the same code running in different places could end up inserting different dates - is that okay? Normally I don't like letting the system local time zone affect things.)
You should generally avoid string conversions unless you really need a string representation of the data. At other times they just cause trouble.
EDIT: You asked for an example. It would be something like:
using (var connection = new SqlConnection(...))
{
connection.Open();
using (var command = new SqlCommand(
"INSERT INTO Foo (Name, RegisterDate) VALUES (#Name, #RegisterDate)",
connection))
{
command.Parameters.Add(new SqlParameter("#Name", SqlDbType.NVarChar))
.Value = name;
// TODO: Consider whether you really want the *local* date, or some
// fixed time zone such as UTC
command.Parameters.Add(new SqlParameter("#RegisterDate", SqlDbType.DateTime))
.Value = DateTime.Today;
command.ExecuteNonQuery();
}
}
Try
string RegisterDate = DateTime.Now.ToString("M-d-yyyy");
and then store in database.
There is no need to manually convert date to different representation. You can go through this Custom Date and Time Format Strings. But, I agree on Jon Skeet's comment below this answer:
If you want to represent a date/time type, use a date/time type. That
way you're able to take advantage of all kinds of things that the
database can do with date/time values, and you'll never get any
non-date/time values in that field.
Note:
DateTime type uses the Gregorian calendar as their default calendar. So, as pointed out by Jon Skeet, this answer won't work with other calenders(Non-Gregorian calendars).
I'm trying to call a stored procedure (on a SQL 2005 server) from C#, .NET 2.0 using DateTime as a value to a SqlParameter. The SQL type in the stored procedure is 'datetime'.
Executing the sproc from SQL Management Studio works fine. But everytime I call it from C# I get an error about the date format.
When I run SQL Profiler to watch the calls, I then copy paste the exec call to see what's going on. These are my observations and notes about what I've attempted:
1) If I pass the DateTime in directly as a DateTime or converted to SqlDateTime, the field is surrounding by a PAIR of single quotes, such as
#Date_Of_Birth=N''1/8/2009 8:06:17 PM''
2) If I pass the DateTime in as a string, I only get the single quotes
3) Using SqlDateTime.ToSqlString() does not result in a UTC formatted datetime string (even after converting to universal time)
4) Using DateTime.ToString() does not result in a UTC formatted datetime string.
5) Manually setting the DbType for the SqlParameter to DateTime does not change the above observations.
So, my questions then, is how on earth do I get C# to pass the properly formatted time in the SqlParameter? Surely this is a common use case, why is it so difficult to get working? I can't seem to convert DateTime to a string that is SQL compatable (e.g. '2009-01-08T08:22:45')
EDIT
RE: BFree, the code to actually execute the sproc is as follows:
using (SqlCommand sprocCommand = new SqlCommand(sprocName))
{
sprocCommand.Connection = transaction.Connection;
sprocCommand.Transaction = transaction;
sprocCommand.CommandType = System.Data.CommandType.StoredProcedure;
sprocCommand.Parameters.AddRange(parameters.ToArray());
sprocCommand.ExecuteNonQuery();
}
To go into more detail about what I have tried:
parameters.Add(new SqlParameter("#Date_Of_Birth", DOB));
parameters.Add(new SqlParameter("#Date_Of_Birth", DOB.ToUniversalTime()));
parameters.Add(new SqlParameter("#Date_Of_Birth",
DOB.ToUniversalTime().ToString()));
SqlParameter param = new SqlParameter("#Date_Of_Birth",
System.Data.SqlDbType.DateTime);
param.Value = DOB.ToUniversalTime();
parameters.Add(param);
SqlParameter param = new SqlParameter("#Date_Of_Birth",
SqlDbType.DateTime);
param.Value = new SqlDateTime(DOB.ToUniversalTime());
parameters.Add(param);
parameters.Add(new SqlParameter("#Date_Of_Birth",
new SqlDateTime(DOB.ToUniversalTime()).ToSqlString()));
Additional EDIT
The one I thought most likely to work:
SqlParameter param = new SqlParameter("#Date_Of_Birth",
System.Data.SqlDbType.DateTime);
param.Value = DOB;
Results in this value in the exec call as seen in the SQL Profiler
#Date_Of_Birth=''2009-01-08 15:08:21:813''
If I modify this to be:
#Date_Of_Birth='2009-01-08T15:08:21'
It works, but it won't parse with pair of single quotes, and it wont convert to a DateTime correctly with the space between the date and time and with the milliseconds on the end.
Update and Success
I had copy/pasted the code above after the request from below. I trimmed things here and there to be concise. Turns out my problem was in the code I left out, which I'm sure any one of you would have spotted in an instant. I had wrapped my sproc calls inside a transaction. Turns out that I was simply not doing transaction.Commit()!!!!! I'm ashamed to say it, but there you have it.
I still don't know what's going on with the syntax I get back from the profiler. A coworker watched with his own instance of the profiler from his computer, and it returned proper syntax. Watching the very SAME executions from my profiler showed the incorrect syntax. It acted as a red-herring, making me believe there was a query syntax problem instead of the much more simple and true answer, which was that I need to commit the transaction!
I marked an answer below as correct, and threw in some up-votes on others because they did, after all, answer the question, even if they didn't fix my specific (brain lapse) issue.
How are you setting up the SqlParameter? You should set the SqlDbType property to SqlDbType.DateTime and then pass the DateTime directly to the parameter (do NOT convert to a string, you are asking for a bunch of problems then).
You should be able to get the value into the DB. If not, here is a very simple example of how to do it:
static void Main(string[] args)
{
// Create the connection.
using (SqlConnection connection = new SqlConnection(#"Data Source=..."))
{
// Open the connection.
connection.Open();
// Create the command.
using (SqlCommand command = new SqlCommand("xsp_Test", connection))
{
// Set the command type.
command.CommandType = System.Data.CommandType.StoredProcedure;
// Add the parameter.
SqlParameter parameter = command.Parameters.Add("#dt",
System.Data.SqlDbType.DateTime);
// Set the value.
parameter.Value = DateTime.Now;
// Make the call.
command.ExecuteNonQuery();
}
}
}
I think part of the issue here is that you are worried that the fact that the time is in UTC is not being conveyed to SQL Server. To that end, you shouldn't, because SQL Server doesn't know that a particular time is in a particular locale/time zone.
If you want to store the UTC value, then convert it to UTC before passing it to SQL Server (unless your server has the same time zone as the client code generating the DateTime, and even then, that's a risk, IMO). SQL Server will store this value and when you get it back, if you want to display it in local time, you have to do it yourself (which the DateTime struct will easily do).
All that being said, if you perform the conversion and then pass the converted UTC date (the date that is obtained by calling the ToUniversalTime method, not by converting to a string) to the stored procedure.
And when you get the value back, call the ToLocalTime method to get the time in the local time zone.
Here is how I add parameters:
sprocCommand.Parameters.Add(New SqlParameter("#Date_Of_Birth",Data.SqlDbType.DateTime))
sprocCommand.Parameters("#Date_Of_Birth").Value = DOB
I am assuming when you write out DOB there are no quotes.
Are you using a third-party control to get the date? I have had problems with the way the text value is generated from some of them.
Lastly, does it work if you type in the .Value attribute of the parameter without referencing DOB?
Just use:
param.AddWithValue("#Date_Of_Birth",DOB);
That will take care of all your problems.
If you use Microsoft.ApplicationBlocks.Data it'll make calling your sprocs a single line
SqlHelper.ExecuteNonQuery(ConnectionString, "SprocName", DOB)
Oh and I think casperOne is correct...if you want to ensure the correct datetime over multiple timezones then simply convert the value to UTC before you send the value to SQL Server
SqlHelper.ExecuteNonQuery(ConnectionString, "SprocName", DOB.ToUniversalTime())