Invalid Cast Exception was unHandled MySQL - c#

When I run the program I get this error:
Invalid Cast Exception was unHandled
This is part of form for fill a database, and visual Studio marks the int cast as the error
MySqlConnection conectar = new MySqlConnection("server=127.0.0.1; database=gymne; Uid=root; pwd=0000000000;");
using (MySqlCommand sqlCommand = new MySqlCommand("SELECT COUNT(*) from Socios where Nombre like #pNombre AND Apellido like #pApellido", conectar))
{
conectar.Open();
sqlCommand.Parameters.AddWithValue("#pNombre", txtNombre.Text);
sqlCommand.Parameters.AddWithValue("#pApellido", txtApellido.Text);
int UsuarioExiste = (int)sqlCommand.ExecuteScalar();//<----"error here"
if (UsuarioExiste > 0)
{
MessageBox.Show("El Socio ya existe!!", "No Guardado", MessageBoxButtons.OK, MessageBoxIcon.Information);
}

The problem is the ExecuteScalar that in MySql returns an Int64 not an Int32. So the invalid cast when you use an explicit cast
With a conversion your error should go away
int UsuarioExiste = Convert.ToInt32(sqlCommand.ExecuteScalar());
You are not alone to fall in this problem
Of course everything that has been said in the answer from Mr Soner Gönül is still applicable and should be done ASAP.

I strongly suspect, you parameterize your LIKE part in a wrong way. You need to use %..% at least to figure out you try to get values that includes those string. Like;
sqlCommand.Parameters.AddWithValue("#pNombre", "%" + txtNombre.Text + "%");
sqlCommand.Parameters.AddWithValue("#pApellido", "%" + txtApellido.Text + "%");
Don't use AddWithValue as much as you can. It may generate unexpected and surprising results sometimes. Use Add method overload to specify your parameter type and it's size.
Also use using statement to dispose your connection and command automatically instead of calling (in somewhere maybe in your code) Close or Dispose methods manually.
By the way, be aware, COUNT(*) returns BIGINT in MySQL and this type mapped with Int64 in .NET side. As Steve mentioned, you can parse this value instead of casting like;
int UsuarioExiste = int.Parse(sqlCommand.ExecuteScalar());
or you can define your UsuarioExiste as long which seems more consistent(?) I think.
long UsuarioExiste = (long)sqlCommand.ExecuteScalar();

Related

Troubleshooting "Data type mismatch in criteria expression." during MS Access Insert.Into

I'm creating a basic customer inventory application, and when converting the code from using SQL Server to using MS Access (which I'm quite a bit less versed in), I ran into a "Data type mismatch" error when trying to do a basic insert.
I've looked into several similar questions here, and double checked the msdn syntax guide, but I can't find a reason why the script I've written would generate that error. I changed my code several times to try and ensure proper data type (ending up with what I have below with explicit typing and adding the value later). I've actually even taken the string and pasted it into MS Access (sans white space and double quotes), and it seems to work just fine with the values given. At this point, I'm really and truly stumped, and I'm wondering if it might just be a quirk with the Oledb adapter? Any help would be appreciated. Thanks.
// SQL query defined elsewhere:
public static readonly string sqlAddCustomerNotes = "INSERT INTO CustomerNotes (Customer_ID, Notes, NotesDate) "
+ "VALUES(#Customer_ID, #Notes, #NotesDate);";
// end sql query
// data access function
public static void addNotes(int customerID, string notes, DateTime notesDate)
{
string query = Scripts.sqlAddCustomerNotes;
using (
OleDbCommand dbCommand = new OleDbCommand()
{
Connection = new OleDbConnection(ConnectionAccess.connString),
CommandType = CommandType.Text,
CommandText = query,
Parameters =
{
new OleDbParameter("#Customer_ID", OleDbType.Integer),
new OleDbParameter("#Notes", OleDbType.LongVarChar),
new OleDbParameter("#NotesDate", OleDbType.DBTimeStamp)
}
}) // end using parenthetical
{ // begin using scope
dbCommand.Parameters[0].Value = customerID;
dbCommand.Parameters[1].Value = notes;
dbCommand.Parameters[2].Value = notesDate;
foreach (OleDbParameter param in dbCommand.Parameters)
{ // replace ambiguous null values with explicit DBNulls.
if (param.Value == null)
{
param.Value = DBNull.Value;
}
}
dbCommand.Connection.Open();
int rowsAffected = dbCommand.ExecuteNonQuery();
dbCommand.Connection.Close();
Console.WriteLine($"Rows affected: {rowsAffected}");
}
} // end addCustomerNotes
/*
table "CustomerNotes" has the following columns:datatypes
CustomerNotes_ID: AutoNumber
Customer_ID: Number
Notes: Memo
NotesDate: Date/Time
CreateDate: Date/Time
test case (in code) was:
#Customer_ID = 5
#Notes = "customer might change last name to simpson."
#NotesDate = {6/26/2019 12:05:39 PM}
*/
It probably is a date, not a timestamp:
new OleDbParameter("#NotesDate", OleDbType.DBDate)
Considering June7's comment about delimiters, it seems the issue lies in some issue inherent to the OleDbParameter type. In SQL Server terms, I do want DateTime (not Date), but representing it as a DBTimeStamp seems to make it unrecognizable by Access.
For the time being, I've sent the date as a VarChar and allowed Access to convert it however its internal engine sees fit. It feels/seems wrong, but it does, in fact, solve the problem.
Parameters =
{
new OleDbParameter("#Customer_ID", OleDbType.Integer),
new OleDbParameter("#Notes", OleDbType.LongVarChar),
new OleDbParameter("#NotesDate", OleDbType.VarChar)
}
EDIT: Just saw June7's latest comment, and there was in fact, an answer in another thread. OleDbType.DBDate doesn't do what I want, but OleDbType.Date does.

C# with Npgsql - Can't write CLR type System.String with handler type Int32Handler

i have problem when im trying to add integer to Postgresql database. Varchars works fine, but when i use code:
var parameter = cmd.CreateParameter();
parameter.Value = Int32.Parse(x.Value.ToString());
Console.WriteLine(parameter.Value);
parameter.ParameterName = x.Key.ToString();
cmd.Parameters.Add(new NpgsqlParameter("confirmations",NpgsqlTypes.NpgsqlDbType.Integer));
for (int search=0; search != cmd.Parameters.Count; search++)
error in executing, where im using:
cmd.ExecuteNonQuery();
sounds like:
Database problem: System.InvalidCastException: Can't write CLR type System.String with handler type Int32Handler\
at lambda_method(Closure , NpgsqlTypeHandler , Object , NpgsqlLengthCache& , NpgsqlParameter )
at Npgsql.NpgsqlParameter.ValidateAndGetLength() in C:\projects\npgsql\src\Npgsql\NpgsqlParameter.cs:line 553
at Npgsql.NpgsqlCommand.ValidateParameters() in C:\projects\npgsql\src\Npgsql\NpgsqlCommand.cs:line 793
at Npgsql.NpgsqlCommand.ExecuteDbDataReader(CommandBehavior behavior, Boolean async, CancellationToken cancellationToken) in C:\projects\npgsql\src\Npgsql\NpgsqlCommand.cs:line 1141
at Npgsql.NpgsqlCommand.ExecuteNonQuery(Boolean async, CancellationToken cancellationToken) in C:\projects\npgsql\src\Npgsql\NpgsqlCommand.cs:line 1042
at Npgsql.NpgsqlCommand.ExecuteNonQuery() in C:\projects\npgsql\src\Npgsql\NpgsqlCommand.cs:line 1025
at BitcoinType.DatabaseManager.MakeInsert(Dictionary`2 requestData) in /Users/kamilkostrzewski/Projects/BitcoinType/BitcoinType/Program.cs:line 261
This did not helped me.
I had this problem and I solved like this. In my database I have a column that type Integer. If you want to add data this column, You should use NpgsqlDbType.Integer datatype. But when I use NpgsqlDbType.String datatype, I get that error.
So you should change your NpgsqlDBtType. I hope it helps you.
Assume you have the following table:
create table foo (
bar integer
)
If you prepare an insert into the table as follows:
NpgsqlCommand cmd = new NpgsqlCommand("insert into foo values (:BAR)", conn);
cmd.Parameters.Add(new NpgsqlParameter("BAR", NpgsqlDbType.Integer));
It's probably pretty obvious that this will throw an error:
cmd.Parameters[0].Value = "Hello";
cmd.ExecuteNonQuery();
For the same reason this would throw an error:
insert into foo values ('Hello')
This will clearly work, as it's an integer all around:
cmd.Parameters[0].Value = 5;
But what you may not know is the following will all still work, since they are compatible datatypes:
cmd.Parameters[0].Value = 5M;
cmd.Parameters[0].Value = 5f;
cmd.Parameters[0].Value = (short)5;
cmd.Parameters[0].Value = (long)5;
However, even though PostgreSQL is tolerant enough to accept this in raw SQL:
insert into foo values ('5')
Npgsql 4 will throw the error you mentioned when you try to do this:
cmd.Parameters[0].Value = "5";
cmd.ExecuteNonQuery();
Interestingly, I'm pretty sure it worked with Npgsql 3.x, but I consider the error an improvement.
Since it is expecting a numeric datatype, the simple solution is to be sure any .Value you assign is also a numeric datatype, ideally an integer:
cmd.Parameters[0].Value = Convert.ToInt32(yourObject);
cmd.ExecuteNonQuery();
With the standard warnings about error trapping and the use of int.TryParse.
From your code above it actually looks like you might be taking something that could already exist as an integer and convert it into a string. If you do away with all that, you may find it works out of the box. In any case, the .Value property needs to be numeric.
It's difficult to understand your code sample above - you create and populate parameter, but then add a completely different instance of NpgsqlParameter to the comment.
However, the error message clearly says that you are trying to write a string as an integer. This happens when you set NpgsqlParameter.Value to a string value, but set its NpgsqlDbType to Integer. Either omit setting NpgsqlDbType altogether (Npgsql will usually infer the correct type from the value) or make sure they are properly aligned.
I was having the same issue with the following code
var utctime = DateTimeOffset.UtcNow.ToString("yyyy-MM-dd HH:mm:ss");
writer.Write(utctime, NpgsqlDbType.TimestampTz);
So basically you are converting utctime to string but while writing to database using type as Timestamp which is not a string. Therefore it throws error as the data is not compatible with the data type.
The fix is to not cast the utctime to string just use it as is. so working solution is
var utctime = DateTimeOffset.UtcNow;
writer.Write(utctime, NpgsqlDbType.TimestampTz);

Setting SQL query parameter to Int32 in C#

I'm having problems with some code I'm trying to write. I'm doing something for suppliers orders, so I have a table which is named "encomendas_fornecedores" with a autoincrement field before the key that is the code of sale which consists in a EF before the number(which is a text field).
Here is the code:
connection.Open();
OleDbCommand comando1 = new OleDbCommand();
OleDbCommand comando2 = new OleDbCommand();
OleDbCommand comando3 = new OleDbCommand();
comando1.Connection = connection;
comando2.Connection = connection;
comando3.Connection = connection;
comando1.CommandText = "INSERT INTO encomendas_fornecedores (cod_encomenda_forn, cod_metodo, cod_forn, total_pagar_forn) VALUES('FO', '" + txtcodmetodo.Text + "', '" + txtcodforn.Text + "', '" + lbltotalapagar.Text + "'); ";// insert into table the values with a FO to cod
comando1.ExecuteNonQuery();
comando2.CommandText = "Select MAX(num_encomenda) From encomendas_fornecedores;";// selecting maximum num encomenda so I can isolate it and add to a text before(btw I do this in php/sql no problems
int numero = Convert.ToInt32(comando2.ExecuteScalar());//max num_encomenda
string codencomendaforn= "EF"+Convert.ToString(numero);// sales code completed
comando3.CommandText = "UPDATE encomendas_fornecedores SET cod_encomenda_forn = '"+codencomendaforn+"' WHERE num_encomenda = '"+ numero +"';";//query that is giving me the problems, it says something like "type of data incorrect in data expression"
comando3.ExecuteScalar();//giving me error this line
connection.Close();
But now here's the catch the cod_encomenda_forn is text and the num_encomenda auto increment as it is in the sql, and I tried to show the query in a textbox to see if its anything is wrong but nothing seems wrong.
"UPDATE encomendas_fornecedores SET cod_encomenda_forn = '"+codencomendaforn+"' WHERE num_encomenda = **'**"+ **numero** +"**'**;";//query that is giving me the problems,it says something like "type of data incorrect in data expression"
You are passing a string numero to a where statement that seems like it is expecting a number. As long as it is numeric it should work, but definitely not gauranteed to work. Second you are passing anothercodencomendaforn string to encomenda what is encomenda 's data type?
It appears that you are not handling potential datatype differences between your c# code and your SQL query. In addition single quoting '' around a value in a SQL statement tells the database engines that it is a string even if that is '1234'. While SQL will automatically convert some values it doesn't always. In addition c# .net library also looks for some conversion etc. before sending the SQL statement. To fix appropriately use parameters that are data typed to the database type in the SQL table. To fix it simply in the statement figure out your data types and fix the '' single quotes appropriately.
PS the people trying to help you in the comments were being nice and telling you the professional way of keeping your job in the future when you graduate after fixing this issue.

convert type 'object' to 'System.Data.SqlClient.SqlCommand Error

Cannot implicitly convert type 'object' to 'System.Data.SqlClient.SqlCommand'. An explicit conversion exists (are you missing a cast?)
I got this error while creating Usercontrol
it is in this code.
protected void gvDetails_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
int Slno = Convert.ToInt32(gvDetails.DataKeys[e.RowIndex].Value.ToString());
var ProductNum = gvDetails.DataKeys[e.RowIndex].Values["ProductNumber"].ToString();
TextBox txtShortDesc = (TextBox)gvDetails.Rows[e.RowIndex].FindControl("ShortDesc");
SqlCommand cmd= SqlHelper.ExecuteScalar(GlobalSettings.DbDSN, CommandType.Text,"UPDATE sydShortDesc set ShortDesc='"+ txtShortDesc.Text+ " ' WHERE ProductNumber='"+ ProductNum +"' ");
cmd.ExecuteNonQuery();
lblresult.ForeColor = Color.Green;
lblresult.Text = username + " Details Updated successfully";
gvDetails.EditIndex = -1;
BindEmployeeDetails();
}
Well presumably your SqlHelper.ExecuteScalar method is declared to return object, not SqlCommand. Indeed, I wouldn't expect it to return SqlCommand - I'd expect it to return the results of executing the given query. I suspect you don't want to call ExecuteScalar in the first place.
As a very important aside, your current code is vulnerable to SQL injection attacks - you should use parameterized SQL instead of embedding values directly into the SQL.
From the name of your function SqlHelper.ExecuteScalar it appears that this function executes the command and return the result set, not a new SqlCommand. That is why you are getting the error.
Couple of other things, You should always use Parameterized queries to save yourself from Sql Injection

trying to read sql statement c#

string queryStr = "select max(patient_history_date_bio) " +
"as med_date, medication_name from biological where " +
"(patient_id = " + patientID.patient_id + ") " +
"group by medication_name;";
using (var conn = new SqlConnection(connStr))
using (var cmd = new SqlCommand(queryStr, conn))
{
conn.Open();
using (SqlDataReader rdr = cmd.ExecuteReader())
{
int count = 0;
while (rdr.Read())
{
MessageBox.Show("test");
med.medication_date[count] = new DateTime();
med.medication_date[count] = DateTime.Parse(rdr["med_date"].
ToString());
MessageBox.Show("test2");
med.medication_name[count] = rdr["medication_name"].ToString();
count++;
}
}
conn.Close();
}
so i'm trying to read this sql statement. "test" message box displays, but not "test2". I tried running the sql statement in VS by itself (in the server explorer), and the sql statement works. it gives me what i want. but somehow, the code doesn't work... does anyone see why?
Assuming patient_id is some sort of integer (or is it a Guid), my assumption is that the current culture of your program is causing the ToString method call on int to be formatted in a way that is returning something that the parser can't parse (e.g. "1,234,567").
Generally, the way you are executing this statement is not a best-practice. While you might not be susceptible to injection attacks if the id is indeed an int (you are most definitely open to them if it's a string), you generally want to parameterize the queries.
The reason for this is not only to protect against injection attacks, but because it will properly format the parameter in the query string according to the type.
Another thing to point out about your code is how you are retrieving the values from the reader. You are effectively calling ToString on the DateTime instance, then calling Parse on the string to get a DateTime back.
This effectively burns cycles. All you need to do is cast (unbox in the case of value types) the value back.
So where you have:
med.medication_date[count] = DateTime.Parse(rdr["med_date"].
ToString());
You should have:
med.medication_date[count] = (DateTime) rdr["med_date"];
All that being said, as to why the second message box is not showing, my first guess is that you are executing this in an event handler in a Windows Forms application, and that an exception is being thrown.
I think that what you will find is that if medication_date is an array, then it hasn't been initialized and you are getting a NullReferenceException or something about the array index being out of bounds.
What is med.medication_date?
If it is an array, maybe it hasn't been initialized yet.
If it is a list, you should assign to it using med.medication_date.Add(value);
Alternatively, as everyone else is saying, the date time conversion may be at fault. Try replacing
MessageBox.Show("test");
With
MessageBox.Show(rdr["med_date"].ToString());
you should direct your debug stuff to the output window...it's muche easier to follow the flow.
system.diagnostics.debug.writeline(rdr["med_date"].ToString());
Without more info, it looks like the line
med.medication_date[count] = DateTime.Parse(rdr["med_date"].ToString());
throws an exception due to an unrecognised date, and the exception is being swallowed by a handler higher up.

Categories