Conversion failed when converting datetime from character string - c#

when i compile the following code , "Conversion failed when converting datetime from character string" exception raises , what is wrong with that ?
code :
DateTime after3Dyas = DateTime.Now.AddDays(3);
try
{
Con.Open();
SqlCommand Command = Con.CreateCommand();
Command.CommandText = "Select * from Forcast Where City='" + city + "' And Date between '" + DateTime.Now.Date + "' and '" + after3Dyas.Date + "'";
SqlDataReader thisReader = Command.ExecuteReader();
int i=0;
while (thisReader.Read())
{
//do something
i++;
}
thisReader.Close();

The database is trying to convert the value from whatever DateTime.ToString is giving you... do you really want to trust that .NET on your calling machine and SQL Server use exactly the same format? That sounds brittle to me.
Avoid this by not putting the value into the SQL directly in the first place - use a parameterized query. This not only avoids conversion issues, but also (equally importantly) avoids SQL injection attacks.
Sample code:
DateTime start = DateTime.Now;
DateTime end = start.AddDays(3);
string sql = #"
SELECT * FROM Forecast
WHERE City = #City AND Date BETWEEN #StartDate AND #EndDate";
// Don't forget to close this somewhere. Why not create a new connection
// and dispose it?
Con.Open();
using (SqlCommand command = new SqlCommand(sql, Con))
{
command.Parameters.Add("#City", SqlDbType.NVarChar).Value = city;
command.Parameters.Add("#StartDate", SqlDbType.DateTime).Value = start;
command.Parameters.Add("#EndDate", SqlDbType.DateTime).Value = end;
using (SqlDataReader reader = command.ExecuteReader())
{
int i = 0;
while (reader.Read())
{
//do something
i++;
}
}
}

You should use parametrized query.
If you don't want to use parametrized query, use CONVERT function:
"Select * from Forcast Where City='" + city + "' And Date = CONVERT(DATETIME,'" + DateTime.Now.ToString("yyyy-MM-dd") + "',120)
CONVERT(Datetime,'2009-12-25',120) converts varchar type to datetime type with specified format. It will also help with sql injection, but parameters are better solution.

Try the format below instead :
DateTime.Now.ToString("yyyy-MM-dd")
But I strongly advice you to use parameters, because of security issues :
Command.CommandText =
"Select * from Forcast Where City=#City And Date between #StartDate and #EndDate";
SqlParameter city = new SqlParameter("#City", SqlDbType.VarChar, 10);
city.Value = yourCityValue;
Command.Parameters.Add(city);
SqlParameter startDate = new SqlParameter("#StartDate", SqlDbType.DateTime);
startDate.Value = yourStartDate;
Command.Parameters.Add(startDate);
SqlParameter endDate = new SqlParameter("#EndDate", SqlDbType.DateTime);
endDate.Value = yourEndDate;
Command.Parameters.Add(endDate);

You should use parameterised queries whenever possible. There are several reasons such as:
You will avoid sql injection attacks.
Execution plans for parameterised queries will be cached by sql server so you will get better performance when executing the same query with different parameter values.
You will avoid need to escape string parameters.
See the following article for more details: http://www.codeproject.com/KB/database/SqlInjectionAttacks.aspx

Related

Error query Sql Server insert, not correct value format C#

I have a problem with inserting data into a sql server 2012.
My problem is that when I save Quantitaand Prezzothe values are changed! what can it be?. Quantita and Prezzo as Money values are taken from a datagridview I leave you under an example with the image of the datagridview used for insertion and the result of insertion into the database.
VALUE WITHIN DATAGRIDVIEW:
AFTER INSERT INTO SQL-SERVER:
SqlConnection conn = db.apriconnessione();
SqlTransaction sqlTran = conn.BeginTransaction();
try
{
//avvio la transazione
SqlCommand command = conn.CreateCommand();
command.Transaction = sqlTran;
//InserimentoBolla
DateTime dataconvertita = Convert.ToDateTime(labelDATADDTMOD.Text);
command.CommandText = "SET IDENTITY_INSERT Bolla ON";
command.ExecuteNonQuery();
command.CommandText = "INSERT INTO Bolla(NumeroDDT,IdCantiere,DataDDT,Agente,RagioneSociale,CodiceCliente,RiferimentiInterni,Importo,Destinazione,Filiale,Magazzino,Preparato,Vettore,TipoTrasporto) VALUES('" + labelNUMDDTMOD.Text+"','"+IdCantiere+"',convert(datetime,'"+dataconvertita+"', 103),'" + labelAgenteMOD.Text+"','"+labelRagioneSocialeMOD.Text+"','"+int.Parse(labelCodiceClienteMOD.Text)+"','"+labelRIFInternoMOD.Text+"','"+float.Parse(labelImportoMOD.Text)+"','"+labelDestMOd.Text+"','"+labelFilialeMOD.Text+"','"+labelMagazzinoMOD.Text+"','"+labelPreparatodaMOD.Text+"','"+labelvettoreMOD.Text+"','"+labelTipoTrasportoMOD.Text+"')";
command.ExecuteNonQuery();
command.CommandText = "SET IDENTITY_INSERT Bolla OFF";
command.ExecuteNonQuery();
//fine bolla
//inserimento articolo
for (int rows = 0; rows < dataGridViewArticoli.Rows.Count; rows++)
{
string Fornitore = dataGridViewArticoli.Rows[rows].Cells[0].Value.ToString();
string ModelloFornitore = dataGridViewArticoli.Rows[rows].Cells[1].Value.ToString();
string SiglaMetel = dataGridViewArticoli.Rows[rows].Cells[2].Value.ToString();
string CodiceMetel = dataGridViewArticoli.Rows[rows].Cells[3].Value.ToString();
string CodiceInterno = dataGridViewArticoli.Rows[rows].Cells[4].Value.ToString();
string Descrizione = dataGridViewArticoli.Rows[rows].Cells[5].Value.ToString();
float prezzo = float.Parse(dataGridViewArticoli.Rows[rows].Cells[6].Value.ToString());
// MessageBox.Show(" "+prezzo);
float quantita = float.Parse(dataGridViewArticoli.Rows[rows].Cells[8].Value.ToString());
// MessageBox.Show("Quantita: "+quantita);
command.CommandText = "INSERT INTO ArticoloCantiere(IdCantiere,IdUtente,CodArt,CodMarca,CodiceInterno,ModelloFornitore,Prezzo,Quantita,Fornitore,Importato) VALUES('" + IdCantiere + "','"+u.IdUtente+"','" + CodiceMetel + "','" + SiglaMetel + "','" + CodiceInterno + "','" + ModelloFornitore + "','" + prezzo + "','" + quantita + "','COMET','BOLLA')";
command.ExecuteNonQuery();
}
//fine inserimento articolo
//conferma delle transazioni con la commit
sqlTran.Commit();
}
catch (Exception ex)
{
sqlTran.Rollback();
MessageBox.Show("Errore nell'inserimento "+ex);
}
conn.Close();
this.DialogResult = DialogResult.OK;
this.Close();
You insert string values with ',' separator into money data type, and this is a problem.
First of all, in SQL Server the decimal separator is ALWAYS '.', not the ','.
Second, you should not pass numbers as strings
Here is the code to reproduce your problem:
declare #t table(col money)
insert into #t values
('1,44');
select *
from #t;
----------
-- 144,00
Money data type accepts input with ',' separator, but it treats it not as decimal separator but thousand separator.
So to resolve it, the best way is pass in numbers as numbers, the worst thing you can do is just replace ',' with '.' before insert:
declare #t table(col money)
insert into #t values
(replace ('1,44', ',', '.'));
select *
from #t;
-----
---1,44
I would suggest adding a breakpoint at:
command.ExecuteNonQuery();
and double check that both values are correct for:
prezzo and quantita
edit: if the values are as expected, please check sql data types.
I would also suggest adding sql parameters, otherwise your code is vulnerable to sql injections:
INSERT INTO
ArticoloCantiere
(field1, field2...)
VALUES
(#value1, #value2...)
then:
command.Parameters.Add(new SqlParameter("#value1", <somevalue>));
command.Parameters.Add(new SqlParameter("#value1", <somevalue>));
...
command.ExecuteNonQuery();
You need to use parameterized queries. This is a BIG DEAL in terms of security, to the point where if you're not doing this you're practically begging to get hacked.
But this isn't just about security. Parameterized queries will also likely fix your formatting issue, because they can also automatically account for things like date formats and text values with single quotes in the data. As a bonus, you'll also typically get a (very small, but measurable) performance boost.
Here's how it will look:
//putting this all in one sql string to execute in one DB call eliminates the need for C# to manage transactions.
// If you're nervous about it, you can add "BEGIN TRANSACTION" and "COMMIT" statements to the SQL.
string sql = "SET IDENTITY_INSERT Bolla ON;\n"
+ "INSERT INTO Bolla (NumeroDDT,IdCantiere,DataDDT,Agente,RagioneSociale,CodiceCliente,RiferimentiInterni,Importo,Destinazione,Filiale,Magazzino,Preparato,Vettore,TipoTrasporto)\n"
+ " VALUES(\n"
+ "#NumeroDDT, #IdCantiere, #DataDDT, #Agente, #RagioneSociale, #CodiceCliente, #RiferimentiInterni, #Importo, #Destinazione, #Filiale, #Magazzino, #Preparato, #Vettore, #TipoTrasporto);\n"
+ "SET IDENTITY_INSERT Bolla OFF;";
using (var conn = db.apriconnessione())
using (var cmd = new SqlCommand(sql, conn))
{
//I have to guess at column types and lengths. Update these parameters to match your DB columns
cmd.Paramerers.Add("#NumeroDDT", SqlDbType.NVarChar, 50).Value = labelNUMDDTMOD.Text;
cmd.Paramerers.Add("#IdCantiere", SqlDbType.Int).Value = IdCantiere;
cmd.Paramerers.Add("#DataDDT", SqlDbType.DateTime).Value = Convert.ToDateTime(labelDATADDTMOD.Text);
cmd.Paramerers.Add("#Agente", SqlDbType.NVarChar, 50).Value = labelAgenteMOD.Text;
cmd.Paramerers.Add("#RagioneSociale", SqlDbType.NVarChar, 50).Value = labelRagioneSocialeMOD.Text;
cmd.Paramerers.Add("#CodiceCliente", SqlDbType.Int).Value = int.Parse(labelCodiceClienteMOD.Text);
cmd.Paramerers.Add("#RiferimentiInterni", SqlDbType.NVarChar, 50).Value = labelRIFInternoMOD.Text;
cmd.Paramerers.Add("#Importo", SqlDbType.Float).Value = float.Parse(labelImportoMOD.Text); //probably should be double or decimal
cmd.Paramerers.Add("#Destinazione", SqlDbType.NVarChar, 50).Value = labelDestMOd.Text;
cmd.Paramerers.Add("#Filiale", SqlDbType.NVarChar, 50).Value = labelFilialeMOD.Text;
cmd.Paramerers.Add("#Magazzino", SqlDbType.NVarChar, 50).Value = labelMagazzinoMOD.Text;
cmd.Paramerers.Add("#Preparato", SqlDbType.NVarChar, 50).Value = labelPreparatodaMOD.Text;
cmd.Paramerers.Add("#Vettore", SqlDbType.NVarChar, 50).Value = labelvettoreMOD.Text;
cmd.Paramerers.Add("#TipoTrasporto", SqlDbType.NVarChar, 50).Value = labelTipoTrasportoMOD.Text;
conn.Open();
cmd.ExecuteNonQuery();
}
Note there are some other improvements in here, too. I didn't re-write the other parts of your code just for the fun of it. But this query parameters are the important part.

Specified cast is not valid

I have an application that get a datetime value from the database but it give me this error
Specified cast is not valid
here is the code
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["Golden_RoseConnectionString"].ConnectionString);
con.Open();
String sel3 = "select Booking_Date from booking where Booking_ID='" + Booking_Id + "'";
SqlCommand cmd3 = new SqlCommand(sel2, con);
SqlDataReader n3 = cmd3.ExecuteReader();
n3.Read();
DateTime Booking_Date = (DateTime)n3.GetSqlDateTime(0);
con.Close();
How can I solve this problem?
You should use:
var Date = Convert.ToDateTime(n3["YOUR_DATE_COLUMN"]);
an sql date is not a .Net DateTime object.
GetSqlDateTime does not do a convertion - see MSDN.
It must be converted - see the SO question as an example

How to convert C# DateTime to MySQL timestamp table column

I'm trying to update a table element of type timestamp called dtprint with the current time (the original value is NULL). The code that I am using is as follows:
MySqlConnection con = new MySqlConnection("Connection_String");
con.Open();
MySqlCommand _cmd = con.CreateCommand();
string dt = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
_cmd.CommandText = "UPDATE requests SET dtprint = " + dt + " WHERE idPerson = " + _personID[index];
_cmd.ExecuteNonQuery();
con.Close();
The exception I keep getting is: Additional information: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '14:03:23 WHERE idPerson = 45' at line 1.
The only thing I can think of is that the Database isn't recognizing the time as a timestamp, any help is greatly appreciated.
Since dt is a string and your dtprint is timestamp, you need to use single quotes when you try to insert it. Like;
"UPDATE requests SET dtprint = '" + dt + "' WHERE
But don't use this way.
You should always use parameterized queries. This kind of string concatenations are open for SQL Injection attacks.
Also use using statement to dispose your database connections and objects.
using(MySqlConnection con = new MySqlConnection(ConnectionString))
using(MySqlCommand _cmd = con.CreateCommand())
{
string dt = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
_cmd.CommandText = #"UPDATE requests SET dtprint = #dtprint
WHERE idPerson = #id";
_cmd.Parameters.Add("#dtprint", MySqlType.TimeStamp).Value = dt;
_cmd.Parameters.Add("#id", MySqlType.Int).Value = _personID[index];
con.Open();
_cmd.ExecuteNonQuery();
}

Execute Datetime from C# to date in SQL Server 2008

I'm new in programming and want you to help me.
I have field of type (date) and when I insert data to database from my website in visual studio 2010 with C#, it Shows me an error during execution.
Can anyone help me?
Thank you
Code behind
string InsMus = "Insert into StoreMus (MusNo,MusDate)" +
"Values (" + Convert.ToInt16(txtMusNo.Text) + ",'" + DateTime.Parse(txtMusDate.Text) + "')";
cmd = new SqlCommand(InsMus , con);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
Don't use string concanation to prevent sql injection. I'm sure that it will also fix this issue.
string InsMus = #"Insert into StoreMus (MusNo,MusDate)
Values (#MusNo, #MusDate);";
using(var con = new SqlConnection("Connection String..."))
using(var cmd = new SqlCommand(InsMus, con))
{
cmd.Parameters.Add("#MusNo", SqlDbType.SmallInt).Value = short.Parse(txtMusNo.Text);
cmd.Parameters.Add("#MusDate", SqlDbType.Date).Value = DateTime.Parse(txtMusDate.Text);
con.Open();
int inserted = cmd.ExecuteNonQuery();
}
Note that i've used the using-statement to ensure that the connection gets disposed/closed.
You could also use DateTime.TryParse instead of DateTime.Parse to prevent an exception that happens when the format of the date is invalid:
DateTime musDate;
if(!DateTime.TryParse(txtMusDate.Text, out musDate))
{
MessageBox.Show("Please enter a valid mus-date.");
return;
}
// here you can use musDate

SQL statement with datetimepicker

This should hopefully be a simple one. When using a date time picker in a windows form, I want an SQL statement to be carried out, like so:
string sql = "SELECT * FROM Jobs WHERE JobDate = '" + dtpJobDate.Text + "'";
Unfortunately, this doesn't actually provide any results because the JobDate field is stored as a DateTime value. I'd like to be able to search for all records that are on this date, no matter what the time stored may be, any help?
New query:
SqlDataAdapter da2 = new SqlDataAdapter();
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "SELECT * FROM Jobs WHERE JobDate >= #p_StartDate AND JobDate < #p_EndDate";
cmd.Parameters.Add ("#p_StartDate", SqlDbType.DateTime).Value = dtpJobDate.Value.Date;
cmd.Parameters.Add ("#p_EndDate", SqlDbType.DateTime).Value = dtpJobDate.Value.Date.AddDays(1);
cmd.Connection = conn;
da2.SelectCommand = cmd;
da2.Fill(dt);
dgvJobDiary.DataSource = dt;
Huge thanks for all the help!
Just one answer: use parametrized queries.
This is for different reasons:
security (no risk of SQL
Injection
no longer those problems for which you're opening a topic
performance.
Thus, write your statement like this:
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "SELECT * FROM Jobs WHERE JobDate = #p_Date"
cmd.Parameters.Add ("#p_Date", SqlDbType.DateTime).Value = dtpJobDate.Value;
If you want to ignore the time, then I think the best bet is to do a range search, if the time is stored in the DB, that is.
Something like this (just the SQL query):
SELECT * FROM Jobs WHERE JobDate >= #p_StartDate AND JobDate < #p_EndDate
StartDate would then be dtpJobDate.Value.Date, and EndDate would be dtpJobDate.Value.Date.AddDays(1)
If the Time is not stored in the DB, then you can do this:
SELECT * FROM Jobs WHERE JobDate = #p_Date
where the search argument should be dtpJobDate.Value.Date
Try dtpJobDate.Value.
Other than the SQL injection stuff in other answers, you can use something like this:
dtpJobDate.Value.ToString("yyyyMMdd HH:mm:ss");
But probably you won't find anything with exact time match, so you can change your query for something like
string sql = "SELECT * FROM Jobs WHERE JobDate BETWEEN '" + dtpJobDateStart.Value.ToString("yyyyMMdd HH:mm:ss") + "' AND '" + + dtpJobDateEnd.Value.ToString("yyyyMMdd HH:mm:ss") + " + "'";
First of all - you have left a door open for SQL injection in your example.
Other than that - to answer your question, you'll have to drop the times off of the JobDate column to get the match done. Try something like this (SQL Injection code left in example for comparison)...
string sql = "SELECT * FROM Jobs WHERE CAST(CONVERT(CHAR(8), JobDate, 112) AS DATETIME) = '" + dtpJobDate.Text + "'";
If you were to parameterize your query - you could do it something like this...
using (var conn = new SqlConnection(myConnectionString))
using (var cmd = new SqlCommand("SELECT * FROM Jobs WHERE JobDate = #JobDate", conn))
{
cmd.Parameters.Add(new SqlParameter("#JobDate", dtpJobDate.Value));
conn.Open();
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// your code here to deal with the records...
}
}
}

Categories

Resources