Exception using DateTime in a parameterized OleDbCommand - c#

I'm trying to insert a System.DateTime into an Access database using a parameterized OleDbCommand in C#. However, it throws a Data type mismatch in criteria expression exception.
Here is my code:
string statement = "INSERT INTO Log (SCTID, LogDateTime, Type, Message, Visible)" +
"VALUES (?, ?, ?, ?, ?);";
OleDbCommand insertCommand = new OleDbCommand(statement, connection);
// Add parameters to the command
insertCommand.Parameters.AddWithValue("#SCTID", OleDbType.Integer).Value = SCTID;
insertCommand.Parameters.AddWithValue("#LogDateTime", OleDbType.DBTime).Value = dateTime;
insertCommand.Parameters.AddWithValue("#Type", OleDbType.Integer).Value = (int)logType;
insertCommand.Parameters.AddWithValue("#Message", OleDbType.BSTR).Value = message;
insertCommand.Parameters.AddWithValue("#Visible", OleDbType.Boolean).Value = visible;
insertCommand.ExecuteNonQuery();
When I comment out the LogDateTime line, the rest of it works. My problem is that no matter what I use for the DateTime type, it doesn't work. I've tried:
OleDbType.Date, OleDbType.DBDate, OleDBType.DBTimeStamp, DbType.Date, DbType.DateTime, DbType.DateTime2
I've also tried:
insertCommand.Parameters.AddWithValue("#LogDateTime", dateTime);
It doesn't work either. Nothing I've read through Google or SO works. Also, note that I do need both date and time, not just a date alone.

insertCommand.Parameters.AddWithValue("#SCTID", OleDbType.Integer).Value = SCTID;
...
That's a very strange way to use AddWithValue. Its second parameter is not the type - it's the value that you want it to have. As given, you just end up using the integral value of enumeration member OleDbType.Integer, and then immediately overwrite it by assigning to Value property. It should be either:
insertCommand.Parameters.AddWithValue("#SCTID", SCTID);
or:
insertCommand.Parameters.Add("#SCTID", OleDbType.Integer).Value = SCTID;
Regarding the statement itself - why do you use ? for placeholders in command text, but then use names when adding parameters to the collection?
Regarding the actual problem - looks like it's a known bug, and the workaround is to truncate milliseconds in your DateTime value before assigning, and to use OleDbType.Date.

Related

Why my Access DB rejects an insert date time?

I have this table created on an Access DB.
string sql = $"CREATE TABLE Eventi (" +
$"id AUTOINCREMENT PRIMARY KEY," +
$"tipologia varchar(255)," +
$"denominazione varchar(255)," +
$"descrizione varchar(255)," +
$"data date," +
$"costo decimal," +
$"prezzo decimal" +
$");";
I use this query to insert new records in the table, but when i exec the query it returns me a 'System.Data.OleDb.OleDbException: 'Data type mismatch in criteria expression.'.
cmd.CommandText = "INSERT INTO Eventi (tipologia,denominazione,descrizione,data,costo,prezzo) VALUES " +
"(#tipologia, #denominazione, #descrizione, #data, #costo, #prezzo);";
Here it is the code to add the querie's parameters:
cmd.Parameters.Add("#id", OleDbType.Integer).Value = v.Id;
cmd.Parameters.Add("#tipologia", OleDbType.VarChar, 255).Value = v.Tipologia;
cmd.Parameters.Add("#denominazione", OleDbType.VarChar, 255).Value = v.Denominazione;
cmd.Parameters.Add("#descrizione", OleDbType.VarChar, 255).Value = v.Descrizione;
cmd.Parameters.Add("#data", OleDbType.Date).Value = v.Data.Date;
cmd.Parameters.Add("#costo", OleDbType.Double).Value = v.Costo;
cmd.Parameters.Add("#prezzo", OleDbType.Double).Value = v.Prezzo;
The real problem in your query is not the type difference between decimal and double. While it is really good practice to always express the correct datatype, in this context, the parameters of type double can be easily converted to decimal if the properties Costo and Prezzo are of type decimal.
The real problem is the presence of a first parameter named #ID while you don't have this field in your fields names and in your parameters placeholders.
In OleDb parameters are not recognized by their name and assigned to their placeholders using the name property. (Indeed the documentation tells us to name these placeholders all with the ? character). In OleDb parameters are positional, so the first parameter will be used as the value for the first placeholder. In your code this results in a shift of every parameter by one position leading to the parameter #Descrizione assigned to the field data and of course that string is not a date.
Just remove the first parameter from your collection and everything should be fine.
Side note. In Access, as well in MySql, you can assign a value to an AUTOINCREMENT/AUTONUMBER field if you really want. SqlServer instead doesn't allow this practice without turning off the IDENTITY property of the column.
ID value is not needed because is an autoincrement field.
As Liam point out in comments you need to use OleDbType.Decimal instead of OleDbType.Decimal
Or you can also do not declare the type (it will be decided automatic)
cmd.Parameters.Add(new SqlParameter("#CODE", myCode));

Conversion failed when converting date and/or time from character string. Inserting value from datetimepicker

I have this syntax on my program:
con.Open();
SqlCommand cmdInsert = new SqlCommand();
cmdInsert.Connection = con;
cmdInsert.CommandText =
"INSERT INTO Customers VALUES (#Firstname, #LastName, #Birthdate)";
cmdInsert.Parameters.Add("#Firstname", SqlDbType.VarChar).Value = txtFirstname.Text;
cmdInsert.Parameters.Add("#LastName", SqlDbType.VarChar).Value = txtLastName.Text;
cmdInsert.Parameters.Add("#BIrthdate", SqlDbType.DateTime).Value = dtpBirthdate.Value;
Whenever this code is executed, I get the error
"Conversion failed when converting date and/or time from character
string"
I'm guessing that the problem roots from "dtpBirthdate.Value" syntax. I tried looking for a correct format for this part of the syntax but I never got lucky.
ADDITIONAL INFO:
I also changed dtpBirthdate.Value to DBNull.Value and it produces the same error.
Use the Date property of the returned DateTime:
dateTimePicker1.Value.Date
I solved it. What's wrong with my code is the sequence of the parameter variables in my insert statement. It should match the sequence of the columns in my database.
Try DateTime.Parse(dtpBirthdate.Value)
Try This:
cmdInsert.Parameters.Add("#BIrthdate", SqlDbType.DateTime).Value =
dtpBirthdate.Value.ToString("yyyy-MM-ddTHH:mm:ss");
cmdInsert.Parameters.Add("#BIrthdate", SqlDbType.String).Value = dtpBirthdate.Value;

c# net connector insert into mysql system datetime error

i am using mysql net connector and i want to insert some data , without datetime it works but
with date time it gives error.
my code is;
da.InsertCommand = new MySqlCommand("INSERT INTO orders( VALUES('',#ORDER_DATE, #DATE_SHIPMENT, #PRODUCT_ID, #QUANTITY, #CUSTOMER_ID, #INVOICE_FEE, #PROD_TYPE, #BRAND, #MODEL, #PRICE, #VAT)", cs);
da.InsertCommand.Parameters.Add("ORDER_DATE", MySqlDbType.DateTime).Value = oRDER_DATEDateTimePicker.Text;
da.InsertCommand.Parameters.Add("DATE_SHIPMENT", MySqlDbType.DateTime).Value = dATE_SHIPMENTDateTimePicker.Text;
da.InsertCommand.Parameters.Add("PRODUCT_ID", MySqlDbType.Int32).Value = pRODUCT_IDTextBox.Text;
da.InsertCommand.Parameters.Add("QUANTITY", MySqlDbType.Decimal).Value = qUANTITYTextBox.Text;
da.InsertCommand.Parameters.Add("CUSTOMER_ID", MySqlDbType.Int32).Value = textiD.Text;
da.InsertCommand.Parameters.Add("INVOICE_FEE", MySqlDbType.VarChar).Value = comboBoxfee.Text;
da.InsertCommand.Parameters.Add("PROD_TYPE", MySqlDbType.VarChar).Value = pROD_TYPETextBox.Text;
da.InsertCommand.Parameters.Add("BRAND", MySqlDbType.VarChar).Value = bRANDTextBox.Text;
da.InsertCommand.Parameters.Add("MODEL", MySqlDbType.VarChar).Value = mODELTextBox.Text;
da.InsertCommand.Parameters.Add("PRICE", MySqlDbType.Decimal).Value = pRICETextBox.Text;
da.InsertCommand.Parameters.Add("VAT", MySqlDbType.Decimal).Value = vATTextBox.Text;
cs.Open();
da.InsertCommand.ExecuteNonQuery();
cs.Close();
error is:
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 'VALUES('','0007-12-2012 00:00:00 ', '0007-12-2012 00:00:00
i guess my datetime format is not recognizing by mysql,in my winform oRDER_DATEDateTimePicker.Text and dATE_SHIPMENTDateTimePicker.Text is short datetime.
thanks
Instead of adding (as a single example of a wider problem) dATE_SHIPMENTDateTimePicker.Text, use DateTime.Parse (etc) to get the actual value as a DateTime, and add that:
var when = DateTime.Parse(dATE_SHIPMENTDateTimePicker.Text);
da.InsertCommand.Parameters.Add(
"DATE_SHIPMENT", MySqlDbType.DateTime).Value = when;
The same applies to all the parameters; integers, dates, decimals, etc. In fact, simply having database code (commands etc) and UI code (text-boxes) in the same method tells me something is very wrong: ideally, you would have that via a method somewhere that takes typed parameters:
void CreateOrder(int foo, string bar, DateTime baz, decimal blop, ...)
{
...
}
It is the job of the UI to turn the human input into real values that make sense to other layers, such as your data-access code.
So done properly, the UI would handle the parsing, and then call a separate method that knows nothing about the UI to talk to the database.
Another approach is for the UI to build an object with typed members and pass that in:
void CreateOrder(Order order)
{
...
}
Then the UI does:
var order = new Order();
order.Id = /* todo... */
/* ...for each property... */
CreateOrder(order);
MySqlDbType.DateTime wants DateTime as parameter, and not string.
Use DateTime.Parse(oRDER_DATEDateTimePicker.Text) or DateTime.ParseExact(oRDER_DATEDateTimePicker.Text, format) where format is custom format for date that you choose. It can be "yyyy-DD-MM" or whatever else you want or need.
You seem to have a few typos in your query:
da.InsertCommand = new MySqlCommand("INSERT INTO orders( VALUES('',#ORDER_DATE, #DATE_SHIPMENT, #PRODUCT_ID, #QUANTITY, #CUSTOMER_ID, #INVOICE_FEE, #PROD_TYPE, #BRAND, #MODEL, #PRICE, #VAT)", cs);
^^^ ^^
Put a space between VALUES and (, and remove the parenthesis after orders:
da.InsertCommand = new MySqlCommand("INSERT INTO orders VALUES ('',#ORDER_DATE, #DATE_SHIPMENT, #PRODUCT_ID, #QUANTITY, #CUSTOMER_ID, #INVOICE_FEE, #PROD_TYPE, #BRAND, #MODEL, #PRICE, #VAT)", cs);
Second, (as others have mentioned), you are not be using the correct DateTime format. MySQL will accept DateTime.Parse as an input, but it should also accept a string in this format:
yyyy-MM-dd HH:mm:ss

compare DateTime in SqlCommand

I have a simple SqlCommand in which I want to return all records within a specified DateTime range. (both Date and Time are involved)
var dataReader = new SqlCommand(
#"Select RecordID from RecordTable
where RecordTable.WorkingDT between '"+ _startDt +"' and '"+ _endDt +"'",
_sqlConnection).ExecuteReader();
how do I have to set the values for _startDt and _endDt?
You can try this:
var dataReader = new SqlCommand(
#"Select RecordID from RecordTable
where RecordTable.WorkingDT between '"+ _startDt.ToString("yyyy-MM-dd HH:mm:ss") +"' and '"+ _endDt.ToString("yyyy-MM-dd HH:mm:ss") +"'",
_sqlConnection).ExecuteReader();
Where _startDt and _endDt are type of DateTime.
If you add them as proper parameters in your command, you don't need to worry about formatting. The added benefit of getting into the habit of using these is that you don't have to worry about SQL injection when you were to supply strings as parameters.
Have a look at http://www.csharp-station.com/Tutorial/AdoDotNet/lesson06
It shows how to use parameters in your queries. I don't think it needs to be spelled out completely.
An example (copy/pasted from the site):
// 1. declare command object with parameter
SqlCommand cmd = new SqlCommand(
"select * from Customers where city = #City", conn);
// 2. define parameters used in command object
SqlParameter param = new SqlParameter();
param.ParameterName = "#City";
param.Value = inputCity;
// 3. add new parameter to command object
cmd.Parameters.Add(param);
// get data stream
reader = cmd.ExecuteReader();
And yes, defining the parameters can be done shorter that 3 lines per parameter. But that's left up to the reader.
#kmatyaszek, While commonly used, the "yyyy-mm-dd HH:mm:ss" date format is not guaranteed to be unambiguously parsed by SQL server. If you must create SQL from concatenating strings (not necessary in this case as René has shown) then you should use the ISO8601 format, which is just the same but with a T in the middle: "yyyy-mm-ddTHH:mm:ss".
http://msdn.microsoft.com/en-us/library/ms190977%28v=sql.90%29.aspx
"The advantage in using the ISO 8601 format is that it is an
international standard. Also, datetime values that are specified by
using this format are unambiguous. Also, this format is not affected
by the SET DATEFORMAT or SET LANGUAGE settings."
For a demonstration why, try this rerunnable Sql script.
if object_id('tempdb..#Foo') is not null drop table #Foo;
create table #Foo(id int, d datetime)
-- Intend dates to be 12th Jan.
set dateformat ymd
insert into #Foo(id, d) values (1, '2012-01-12 01:23:45') -- ok
insert into #Foo(id, d) values (2, '2012-01-12T01:23:45') -- ok
set dateformat ydm
insert into #Foo(id, d) values (3, '2012-01-12 01:23:45') -- wrong!
insert into #Foo(id, d) values (4, '2012-01-12T01:23:45') -- ok
select * from #Foo order by id
if object_id('tempdb..#Foo') is not null drop table #Foo;

Procedure or Function Expects Parameter Which Was Not Supplied #2

I am currently trying to complete a transaction for a web based app, however;
Procedure or function 'completeTransaction' expects parameter '#dateTime', which was not supplied.
Here is copy of the function.
public static void completeTransaction(string storeCode, string employeeId, DateTime Date, string itemListNoId)
{
using (SqlConnection conn = new SqlConnection("Data Source = ; Initial Catalog =Business ; Integrated Security = true;"))
{
using (SqlCommand command = new SqlCommand("dbo.completeTransaction", conn))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#storeCode", SqlDbType.Int).Value = storeCode;
command.Parameters.Add("#employeeId", SqlDbType.Int).Value = employeeId;
**command.Parameters.Add("#Date", SqlDbType.DateTime).Value = Date;**
command.Parameters.Add("#itemListNoId", SqlDbType.Int).Value = itemListNoId;
conn.Open();
command.ExecuteNonQuery();
conn.Close();
}
}
}
My sql table contains the following tables and types (storeCode, INT, employee, INT, Date, DATETIME, itemListNoId, INT)
You do not pass a parameter called #dateTime. It seems like this line
command.Parameters.Add("#Date", SqlDbType.DateTime).Value = Date;
Should be
command.Parameters.Add("#dateTime", SqlDbType.DateTime).Value = Date;
But without the SP source code it is hard to be sure. Keep in mind that SQL Server is complaining about the NAME of the parameter not about its type.
expects parameter '#dateTime'
You passed a parameter named #Date.
the name of the parameter is wrong:
command.Parameters.Add("#dateTime", SqlDbType.DateTime).Value = Date;
If you are getting this and you have passed in the correctly named parameter, check that the CommandType is set to Stored procedure
cmd.CommandType = CommandType.StoredProcedure;
I was seeing these same symptoms spent an embarrassingly long time tracking down how each parameter was getting to the stored proc.
As previous answers have correctly mentioned, most probable reasons for this error are either forgetting to add parameter(s) to the SqlCommand or forgetting to set command's type to CommandType.StoredProcedure
In case you have already set above correctly and still pulling your hair, then this might be the reason.
If you set parameters value to null (e.g. mySQLParam1.Value = valuePassedToMe and if valuePassedToMe is null) then you will get the same error (i.e. Procedure or function '...' expects parameter '...', which was not supplied).
This can be solved by assigning DBNull.Value when the value needs to be null
i.e.
mySQLParam1.Value = valuePassedToMe ?? (object)DBNull.Value;
When you assign null to a parameter ADO.Net converts it to default. Below is an example from SQL Server Profiler.
exec dbo.MyStoredProcedure #mySQLParam1=default,#mySQLParam2=default,#mySQLParam3=default,...
When you assign DBNull.Value the generated SQL becomes:
exec dbo.MyStoredProcedure #mySQLParam1=NULL,#mySQLParam2=NULL,#mySQLParam3=NULL,...

Categories