Why "Specified cast is not valid" error?

J

Jack MacRank

Hello,

I'm coding a webform application in C# (ASP.NET 1.1 SP1 with VS.NET 2003 Pro
on WinXP SP2 using IIS 5.1).

I created a seperate "data" class to house all the MySQL connection and sql
command methods. This is exactly what the Microsoft Data Access Application
Block assembly does but I coded my own simple, custom class.

I have a method named "ExecuteAggregate" that takes in a sql string like
"SELECT COUNT(*) FROM users", executes it like ExecuteScalar() does and
returns an object typed value. Here is the code below:

***CODE BLOCK***

public static object ExecuteAggregate(string SQL)
{

MySqlCommand myCmd = new MySqlCommand(SQL, myConn);

object retval = myCmd.ExecuteScalar();

return retval;

}

***CODE BLOCK***

I use the above method in the page_load event as shown below. The project
builds without error or warning but the page errors out when it executes.

***CODE BLOCK***

private void Page_Load(object sender, System.EventArgs e)
{

string userCount;

Data.Connect();

//>>>>>"Specified cast is not valid." exception occurs on next line!

userCount = (string)Data.ExecuteAggregate("SELECT COUNT(*) FROM users");

lblBalance.Text = userCount;

Data.Disconnect();

}

***CODE BLOCK***

I have no idea why this is erroring out when executing and not during
building. Convert.ToInt32() fixes this but I would like to know why a C#
cast will not.

Thanks for your help in advance!
 
J

Jack MacRank

"Rob Lykens" wrote
Try
convert.toString(Data.ExecuteAggregate("SELECT COUNT(*) FROM users"));

Yes Rob, that does work and that's what I meant to write at the bottom of my
original message, not Int32(). But why doesn't cast work in this situation?
Microsoft's Data Access Application Block examples have the exact structure
of my code but it errors out when executed.

Thanks
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

Have you tried:

userCount = Data.ExecuteAggregate("SELECT COUNT(*) FROM users").ToString();

instead of using a casting ?
if still getting error, assig the return value to an object instance and put
a break point in the next line to see what you are getting as response.

Cheers,
 
J

Jack MacRank

Ignacio Machin ( .NET/ C# MVP ) wrote
Hi,

Have you tried:

userCount = Data.ExecuteAggregate("SELECT COUNT(*) FROM
users").ToString();

Ignacio, this works perfect but in other places I will need to cast/convert
it as an int type. I will play around with breakpoints before the object is
returned to see if anything funny is going on but I'm still wondering why a
simple cast won't work.

Thanks!
 
J

Jon Skeet [C# MVP]

***CODE BLOCK***

private void Page_Load(object sender, System.EventArgs e)
{

string userCount;

Data.Connect();

//>>>>>"Specified cast is not valid." exception occurs on next line!

userCount = (string)Data.ExecuteAggregate("SELECT COUNT(*) FROM users");

lblBalance.Text = userCount;

Data.Disconnect();

}

***CODE BLOCK***

I have no idea why this is erroring out when executing and not during
building. Convert.ToInt32() fixes this but I would like to know why a C#
cast will not.

Your C# is expecting the reference returned by Data.ExecuteAggregate to
*be* a string. It's not. Try casting to int instead - or print out
Data.ExecuteAggregate(...).GetType() to find out what type is actually
returned.
 
M

Mohamoss

hi
i guess it is not working becasue that you are custing it as String , while
the returned value is int . ( and this is what is done by the
convertToInt())
try
userCount =(int) Data.EcexuteAggregate("your query");
hope this is it
Mohamed Mahfouz
MEA Developer Support Center
ITworx on behalf of Microsoft EMEA GTSCr
 
S

Stefan Simek

Jack MacRank said:
Hello,

I'm coding a webform application in C# (ASP.NET 1.1 SP1 with VS.NET 2003
Pro on WinXP SP2 using IIS 5.1).

I created a seperate "data" class to house all the MySQL connection and
sql command methods. This is exactly what the Microsoft Data Access
Application Block assembly does but I coded my own simple, custom class.

I have a method named "ExecuteAggregate" that takes in a sql string like
"SELECT COUNT(*) FROM users", executes it like ExecuteScalar() does and
returns an object typed value. Here is the code below:

***CODE BLOCK***

public static object ExecuteAggregate(string SQL)
{

MySqlCommand myCmd = new MySqlCommand(SQL, myConn);

object retval = myCmd.ExecuteScalar();

return retval;

}

***CODE BLOCK***

I use the above method in the page_load event as shown below. The project
builds without error or warning but the page errors out when it executes.

***CODE BLOCK***

private void Page_Load(object sender, System.EventArgs e)
{

string userCount;

Data.Connect();

//>>>>>"Specified cast is not valid." exception occurs on next line!

userCount = (string)Data.ExecuteAggregate("SELECT COUNT(*) FROM users");

lblBalance.Text = userCount;

Data.Disconnect();

}

***CODE BLOCK***

I have no idea why this is erroring out when executing and not during
building. Convert.ToInt32() fixes this but I would like to know why a C#
cast will not.

Thanks for your help in advance!

I'd advise strongly for the Convert.ToXXX() approach, as it won't break your
code if a future version of MySQL (or the provider) decides to return the
COUNT(*) as long instead of int.
The C# cast works as follows:

- Check if the object is exactly of the requested type / implements the
requested interface (null is allowed for reference types)
- Throw an exception if it isn't
- Assign the reference / unbox for value types

On the other hand, the Convert.ToXXX(object) function makes it's best effort
to convert the value, if it's possible. So it can convert byte, sbyte,
short, etc... to int. And the overhead of calling the conversion function is
absolutely insignificant, as the time spent in the ExecuteScalar() method is
thousands of times longer.

HTH,
Stefan
 
J

Jack MacRank

Stefan,

I set a breakpoint and looked at the GetType() of "retval" after the query
executed. I was surprised to see it was of Int64 type. I didn't know
C#/.NET automatically converted an object variable to another type...I
thought it would just be a generic object type and then I could cast it to
whatever I wanted it to.

I'm still a little confused why I can't cast an Int64 to String but I will
take your advice and use .ToString() and Convert.ToInt32() when I want a
string or integer.

Thanks to everyone who responded to my question!
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

the query you have should not return a string, hence you need to convert
that value.
You may cast it to a numeric value ( maybe excepting byte ) without much
problem

Now, my advice in this cases is play safe and use Convert.XXX a casting
may be problematic, even for numeric values. it depends of the DB engine
internal types.


It should not intruduce much overhead calling Convert.ToString( string )
or Convert.ToInt32( int ) so the performance should not be affected

Cheers,
 
K

Kurt

The result is an int and can't be cast to type string. Call the
ToString() method rather then typecast.


Jack MacRank said:
Hello,

I'm coding a webform application in C# (ASP.NET 1.1 SP1 with VS.NET 2003 Pro
on WinXP SP2 using IIS 5.1).

I created a seperate "data" class to house all the MySQL connection and sql
command methods. This is exactly what the Microsoft Data Access Application
Block assembly does but I coded my own simple, custom class.

I have a method named "ExecuteAggregate" that takes in a sql string like
"SELECT COUNT(*) FROM users", executes it like ExecuteScalar() does and
returns an object typed value. Here is the code below:

***CODE BLOCK***

public static object ExecuteAggregate(string SQL)
{

MySqlCommand myCmd = new MySqlCommand(SQL, myConn);

object retval = myCmd.ExecuteScalar();

return retval;

}

***CODE BLOCK***

I use the above method in the page_load event as shown below. The project
builds without error or warning but the page errors out when it executes.

***CODE BLOCK***

private void Page_Load(object sender, System.EventArgs e)
{

string userCount;

Data.Connect();

//>>>>>"Specified cast is not valid." exception occurs on next line!

userCount = (string)Data.ExecuteAggregate("SELECT COUNT(*) FROM users");

userCount = Data.ExecuteAggregate("SELECT COUNT(*) FROM
users").ToString()
 
J

Jon Skeet [C# MVP]

Jack MacRank said:
I set a breakpoint and looked at the GetType() of "retval" after the query
executed. I was surprised to see it was of Int64 type. I didn't know
C#/.NET automatically converted an object variable to another type...I
thought it would just be a generic object type and then I could cast it to
whatever I wanted it to.

I'm still a little confused why I can't cast an Int64 to String but I will
take your advice and use .ToString() and Convert.ToInt32() when I want a
string or integer.

Thanks to everyone who responded to my question!

I *strongly* suggest you abandon database access for the moment and
read a good book on the basics of .NET, in particular the type system.
Then read up on what casts do in C#.

I know it may sound like a backward step, but getting a good handle on
the basics is vital for writing decent code. For instance, you don't
always want to call .ToString or Convert.ToInt32() - it depends
entirely on the circumstances.
 
N

Nancy Rodriguez

Thanks, I was having the same casting problem and solved it following
your instructions of using the ToString method. I do not understand why
a simple cast will not work on this situation... but is working now.
N.R.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top