Specified cast is not valid. SQL Parameter - c#

I keep getting back specified cast is not valid on the int result = myDataReader.GetInt32(0); line when running the query using the parameter.
The thing is if I replace #Reg with text 'WM07 OGR' it works fine. However the string reg returns this so why the error?
string reg = RadComboBox1.SelectedValue;
//prepare sql statements
Command = new OleDbCommand(#"SELECT MAX(Fuel.NO_ODOMETER_LAST) AS PrevMiles
FROM (Fuel INNER JOIN Vehicle ON Fuel.TX_VIN = Vehicle.TX_VIN)
WHERE (Vehicle.TX_VEHNUMBER = '#Reg')", conn);
Command.Parameters.AddWithValue("#Reg", OleDbType.WChar);
Command.Parameters["#Reg"].Value = reg;
myDataReader = Command.ExecuteReader();
if (myDataReader.Read())
{
int result = myDataReader.GetInt32(0);
Prev_Mileage.Text = result.ToString();
}
//cleanup objects
myDataReader.Close();
conn.Close();

The thing is if I replace #Reg with text 'WM07 OGR' it works fine.
However the string reg returns this so why the error?
It seems that you get the error if the query returns null because there is no matching TX_VEHNUMBER, then the cast to int fails.
So you have to check if it's null:
int result = 0; // insert default
if(!myDataReader.IsDbNull(0))
result = myDataReader.GetInt32(0)
Apart from that it doesn't work because your parameter is interpreted as value, you have wrapped it in apostrophes here:
WHERE (Vehicle.TX_VEHNUMBER = '#Reg')
You just have to do this:
WHERE (Vehicle.TX_VEHNUMBER = #Reg)

Try some thing like this.
Command = new OleDbCommand(#"SELECT MAX(Fuel.NO_ODOMETER_LAST) AS PrevMiles
FROM (Fuel INNER JOIN Vehicle ON Fuel.TX_VIN = Vehicle.TX_VIN)
WHERE (Vehicle.TX_VEHNUMBER = #Reg)", conn);
Or
Command = new OleDbCommand(#"SELECT MAX(Fuel.NO_ODOMETER_LAST) AS PrevMiles
FROM (Fuel INNER JOIN Vehicle ON Fuel.TX_VIN = Vehicle.TX_VIN)
WHERE (Vehicle.TX_VEHNUMBER = '?')", conn);
Or
Command = new OleDbCommand(#"SELECT MAX(Fuel.NO_ODOMETER_LAST) AS PrevMiles
FROM (Fuel INNER JOIN Vehicle ON Fuel.TX_VIN = Vehicle.TX_VIN)
WHERE (Vehicle.TX_VEHNUMBER = ?)", conn);
For more reference see following links.
http://www.java2s.com/Code/CSharp/Database-ADO.net/PassparametertoOleDbCommand.htm
http://blogs.msdn.com/b/wriju/archive/2008/01/24/ado-net-oledbcommand-parameterized-query-sequence-rule.aspx

Since it's getting into the below block...
if (myDataReader.Read())
{
int result = myDataReader.GetInt32(0);
Prev_Mileage.Text = result.ToString();
}
...I assume you have a record. I'd check the DataType of NO_ODOMETER_LAST, as it might be a varchar or something other than an int. If thats a case, you might need to use a TryParse.

Related

Data Type Mismatch error in Criteria expression in Select query C# query

My sample code is as follows, I am getting following error;
Data Type Mismatch error in criteria expression.
Details => ScannerAlarmLimits is my table from .mdb database.
string jointS = dsetChamberS1.Tables[0].Rows[tot][0].ToString();
int select1S = Convert.ToInt32(jointS);
string sqlQuery1S = "SELECT TMin,TMax,HMin,HMax from ScannerAlarmLimits WHERE ScannerID='" +select1S+ "'";
OleDbCommand cmd1S = new OleDbCommand(sqlQuery1S, conn);
OleDbDataAdapter adapter1S = new OleDbDataAdapter(cmd1S);
adapter1S.Fill(dsetTempS, "ScannerAlarmLimits");
I just added single quote in the condition of where clause, now its working.
var query = "SELECT * from checkinout where read <> '1'";
If your ScannerID column is integer, then you should not use single quotes with it. Single quotes are for characters. Like;
WHERE ScannerID = " + select1S;
But as a better way, you should always use parameterized queries. This kind of string concatenations are open for SQL Injection attacks. Aka bobby-tables.
And use using statement to dispose your connections, commands and adapters.
string jointS = dsetChamberS1.Tables[0].Rows[tot][0].ToString();
int select1S = Convert.ToInt32(jointS);
using(var conn = new OleDbConnection(conString))
using(var cmd1S = conn.CreateCommand())
{
cmd1S.CommandText = "SELECT TMin,TMax,HMin,HMax from ScannerAlarmLimits WHERE ScannerID = #id";
cmd1S.Parameters.AddWithValue("#id", OleDbType.Integer).Value = select1S;
using(var adapter1S = new OleDbDataAdapter(cmd1S))
{
adapter1S.Fill(dsetTempS, "ScannerAlarmLimits");
}
}

.Net MySql User Defined Variable as Output Parameter

I've been searching for a while but the answers I find usually involve stored procedures or different functionality.
I am trying to execute a reader and also return a scalar in the one query. I thought I could do this using an output parameter, but I get an exception to check my syntax near NULL = #rows_found(), so it appears the output parameter is not getting initialized.
Basically I need to know if this is possible as I haven't found a code sample like this that works.
command.CommandText = #"
SELECT SQL_CALC_FOUND_ROWS
accounting.*
FROM
accounting
WHERE
transaction_type = #transaction_type
LIMIT
#index, #results;
SET #total_rows = FOUND_ROWS();
";
command.Parameters.AddWithValue("transaction_type", transaction_type);
command.Parameters.AddWithValue("index", index);
command.Parameters.AddWithValue("results", results);
MySqlParameter totalRows = new MySqlParameter("total_rows", 0);
totalRows.Direction = System.Data.ParameterDirection.Output;
command.Parameters.Add(totalRows);
using (MySqlDataReader dr = command.ExecuteReader())
{
while (dr.Read())
invoices.Add(new AccountingDataModel(dr));
}
invoices.Total = (int)totalRows.Value;
cmd.Parameters["#output"].Value.ToString()
Use command object to access your out parameter ....
you can not access out perameter directly.
You Should use like
invoices.Total = Convert.ToInt32(command.Parameters["total_rows"].Value.ToString())
example for stored procedure
MySqlCommand cmd = new MySqlCommand(nameOfStoredRoutine, connection);
cmd.CommandType = CommandType.StoredProcedure;
//input parameters
for (int i = 0; i < (parameterValue.Length / 2); i++)
{
cmd.Parameters.AddWithValue(parameterValue[i, 0], parameterValue[i, 1]);
cmd.Parameters[parameterValue[i, 0]].Direction = ParameterDirection.Input;
parameterList = parameterList + parameterValue[i,0] + " " + parameterValue[i,1] + " ";
}
//single output parameter
cmd.Parameters.AddWithValue("#output", MySqlDbType.Int32);
cmd.Parameters["#output"].Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery(); //Execute command
return Convert.ToInt32(cmd.Parameters["#output"].Value.ToString());
It seems that this is not possible. From the documentation of MySqlParameter's members for the Direction property:
Gets or sets a value indicating whether the parameter is input-only, output-only, bidirectional, or a stored procedure return value parameter. As of MySQL version 4.1 and earlier, input-only is the only valid choice.
So the parameter is, no matter what you set Direction to, always an input parameter. If you change the value from null to anything else (e.g. 15) you should see that the generated query is something like
SET 15 = FOUND_ROWS()
Eventually i ended up running two queries. Probably this is not as performant as it could be, but at least it gets the desired result (using EF Core):
using (var context = new MyDbContext(...))
{
context.Database.OpenConnection();
var estates = context.MySet
.FromSql("SELECT SQL_CALC_FOUND_ROWS * FROM myset LIMIT 25 OFFSET 25")
.ToList();
var cmd = context.Database.GetDbConnection().CreateCommand();
cmd.CommandText = "SELECT FOUND_ROWS()";
var rows = (long)cmd.ExecuteScalar();
context.Database.CloseConnection();
}

parameterized with session and query string

I am facing an error message and i didnt know the reason with me sql statement as at line:
DACatPgeVIPLIST.Fill(dsCatPgeVIPLIST);
It's showing this message can you help me with it:
The parameterized query (#Country nvarchar(7),#Category nvarchar(4000))SELECT a.[AdsID], expects the parameter #Category, which was not supplied.
Code:
if (Session["location"] != null)
{
using (SqlConnection CatPgeVIPLISTsqlCON = new SqlConnection(cs))
{
CatPgeVIPLISTsqlCON.Open();
SqlDataAdapter DACatPgeVIPLIST = new SqlDataAdapter("SELECT a.[AdsID], a.[Country], a.[State], a.[City], a.[AdsTit], SUBSTRING(a.[AdsDesc], 1, 70) as AdsDesc, a.[AdsPrice], a.[Img1] FROM [ads] as a INNER JOIN [UserInfo] as u on u.UID = a.UID WHERE a.[Country] = #Country and a.[Category] = #Category and u.VIP = 'Yes'", cs);
string location = Convert.ToString(Session["location"]);
string category = Request.QueryString["category"];
DACatPgeVIPLIST.SelectCommand.Parameters.AddWithValue("#Country", location);
DACatPgeVIPLIST.SelectCommand.Parameters.AddWithValue("#Category", category);
DataSet dsCatPgeVIPLIST = new DataSet();
DACatPgeVIPLIST.Fill(dsCatPgeVIPLIST);
CatPgeVIPLIST.DataSource = dsCatPgeVIPLIST.Tables[0];
CatPgeVIPLIST.DataBind();
}
}
It's possible for the following line of code to assign null to category:
string category = Request.QueryString["category"];
You could possibly get around it like this, which converts null to an empty string:
string category = Convert.ToString(Request.QueryString["category"]);
Or you could try passing DBNull.Value instead of null (untested):
DACatPgeVIPLIST.SelectCommand.Parameters
.AddWithValue("#Category", (object)category ?? DBNull.Value);

DataReader IndexOutofRangeException was unhandled by user code

I ran into another issue again. I was trying to get data from the database using DataReader but I got the error when i was testing my code. Can anyone help me out? The error occurred at this line:
chkAssess = readAssess[columnName].ToString();
Below is the code snippet:
public string CheckAssess(string emailAddress, string columnName)
{
string chkAssess = "";
SqlDataReader readAssess;
//readAssess = new SqlDataReader();
string MgrAssessQry = "SELECT '"+columnName+"' FROM tblAllUsers";
//MgrAssessQry += " WHERE email ='" + emailAddress + "'";
SqlCommand cmdReadAssess = new SqlCommand(MgrAssessQry, cn);
cn.Open();
readAssess = cmdReadAssess.ExecuteReader();
while(readAssess.Read())
{
// Add the rows
chkAssess = readAssess[columnName].ToString();
}
return chkAssess;
}
try to use column name without ''
select something from table
instead of
select 'something' from table
for security reasons, don't create sql queries in that way (by concatenating strings) - use #parameters instead
2. close the reader at the end
Try this:
public string CheckAssess(string emailAddress, string columnName)
{
string chkAssess = "";
SqlDataReader readAssess;
//readAssess = new SqlDataReader();
string MgrAssessQry = "SELECT #Column_Name FROM tblAllUsers";
SqlCommand cmdReadAssess = new SqlCommand(MgrAssessQry, cn);
cmdReadAssess.Parameters.AddWithValue(new SqlParameter("Column_Name", columnName));
cn.Open();
readAssess = cmdReadAssess.ExecuteReader();
while(readAssess.Read())
{
// Add the rows
chkAssess = readAssess.GetString(0);
}
return chkAssess;
}
You have got several problems here.
Check whether your readAssess has rows like below.
if(readAssess.HasRows)
If it doesn't have rows then trying
chkAssess = readAssess.GetString(0);
would throw this error, as Arrays are index-based.
So your code should be like below
if(readAssess.HasRows)
{
while(readAssess.Read())
{
chkAssess = readAssess.GetString(0);
}
}
Other problem is you need to close both the reader & the connection afterwards.
readAssess.Close();
cn.Close();
Also your code is potentially vulnerable to SQL Injection.
if (reader.HasRows)
{
while (reader.Read())
{
int result = Convert.ToInt32(reader.GetString(0));
Console.WriteLine(result);
}
}
The most important thing is check the query first by executing in SQL Server and see if any result is coming or not.
Secondly based on the type of output you are receiving cast it to that particular data type (important).Mostly everyone is saving the data in varchar so.

put values from Inner join in object that is in an object

I have the following sql command with an Inner join:
SqlCommand cmd = new SqlCommand(#"SELECT c.comment_Id, c.date, c.comment, c.rating, a.registration_Date, a.username, a.email, a.profile_Image FROM News_comments c INNER JOIN News_accounts a ON c.account_Id=a.account_Id WHERE c.news_Id = #news_Id", conn);
cmd.Parameters.Add("news_Id", SqlDbType.Int).Value = news_Id;
conn.Open();
I want to put the values from a (News_accounts) in the object account that is in itself in the object newsComment which is located in a generic List, List newsComments.
I do that like this:
using (SqlDataReader reader = cmd.ExecuteReader()) {
while (reader.Read()) {
Comments newsComment = new Comments();
newsComment.comment_Id = int.Parse(reader["comment_Id"].ToString());
newsComment.date = DateTime.Parse(reader["date"].ToString());
newsComment.comment = reader["comment"].ToString();
newsComment.rating = int.Parse(reader["rating"].ToString());
newsComment.account.Registration_Date = DateTime.Parse(reader["registration_Date"].ToString());
newsComment.account.Username = reader["username"].ToString();
newsComment.account.Email = reader["email"].ToString();
newsComment.account.Profile_Image = reader["profile_Image"].ToString();
newsComments.Add(newsComment);
}
return newsComments;
}
Comments has a constructor:
public Comments(int comment_Id, DateTime date, string comment, int rating, Accounts account) {
this.comment_Id = comment_Id;
this.date = date;
this.comment = comment;
this.rating = rating;
this.account = account;
}
And Accounts account as well:
public Accounts(int account_Id, DateTime registration_Date, string email, string username, string profile_Image, string homepage, string about, bool admin) {
this.account_Id = account_Id;
this.registration_Date = registration_Date;
this.email = email;
this.profile_Image = profile_Image;
this.homepage = homepage;
this.about = about;
this.admin = admin;
}
Up until rating all goes well and the values are being put in the newsComment object, however, when it reaches the values that need to be put in the object account that is located in the object newsComment, it gives a NullReferenceException.
I know this means that it doesn't have a value but I can't seem to find why it has no value.
I've looked checked my Inner join with sql server 2008 query designer, and that works
so it's got to be the object but I don't see the problem.
please help me :)
greetings
newsComment.account You have to initialize that object before accessing its fields, properties, or methods. Something like this:
newsComment.account = new Account();
newsComment.account.Registration_Date = DateTime.Parse(reader["registration_Date"].ToString());
newsComment.account.Username = reader["username"].ToString();
newsComment.account.Email = reader["email"].ToString();
newsComment.account.Profile_Image = reader["profile_Image"].ToString();
... or you can do it from the constructor of the Comments class, the one which takes no arguments.
As a side note: maybe you should consider using an ORM, like LINQ to SQL or Entity Framework. It's what they do.
You are not instantiating your account object so it is null

Categories