casting ExecuteScalar() result c# - c#

why would this work
int collectionCharge = (int)cmdCheck.ExecuteScalar();
but this produces an exception
double collectionCharge = (double)cmdCheck.ExecuteScalar();
System.InvalidCastException: Specified cast is not valid.
why would it not be valid?
EDIT
I am trying to simply return a single result from a query, that gets the price of some freight. So I can't turn this into an int because it must have decimals, hence trying to cast to a double. I am still learning asp.net so if there's a better way to achieve this, please do point me in the right direction :)
EDIT 2
the full code with SQL...
using (SqlCommand cmdCheck = new SqlCommand("SELECT FREIGHT_PRICE FROM FREIGHT_QUOTER_BELNL_NEW WHERE CUSTOMER_NO = #CUSTOMER_NO AND COUNTRY = #COUNTRY AND ROUND(WEIGHT_FROM,0) < #WEIGHT AND ROUND(WEIGHT_TO,0) >= #WEIGHT AND SHIPVIA = '48';", connection))
{
double collectionCharge = (double)cmdCheck.ExecuteScalar();
FreightAmount = collectionCharge;
}

The problem here is that ExecuteScalar is returning an int which is boxed into an object. In order to convert to a double you must first unbox to an int then convert to a double
double collectionCharge = (double)(int)cmdCheck.ExecuteScalar();

Use the Convert.ToXXX to avoid invalid cast exceptions.
I.E
collectionCharge=Convert.ToDouble(cmdCheck.ExecuteScalar());
As it appears that ExecuteScalar returns an Object so the code:
double collectionCharge = (double)cmdCheck.ExecuteScalar();
Could still fail

With thanks to #DJKRAZE.
I updated my query to SELECT CASE(FREIGHT_PRICE AS FLOAT) which now works with the (double) cast.
double collectionCharge = (double)cmdCheck.ExecuteScalar();

After reading all answers, I had a case of receiving the Decimal values indeed, and the solution was easy!
I just declared the function as string and received the Decimal value as string!
public static string Sals_AccountExpensesGetSums(int accountID)
{
SqlParameterHelper sph = new
SqlParameterHelper(ConnectionString.GetWriteConnectionString(),
"sals_AccountExpenses_GetAllSums", 1);
sph.DefineSqlParameter("#AccountID", SqlDbType.Int, ParameterDirection.Input, accountID);
string res = sph.ExecuteScalar().ToString();
return res;
}
and in the business layer i changed the result to double!
public static decimal GetAccountExpensesSums(int accountId)
{
string res = "";
decimal sums = 0;
res = DBAccount.Sals_AccountExpensesGetSums(accountId);
// check so we will not have exception
if ( res != "")
sums = Convert.ToDecimal(res);
return sums;
}
and the result was perfect as needed: 889678.70

I would recommend using this code:
object o = c.ExecuteScalar();
if (o != null)
{
int x = Int32.Parse(o.ToString());
}
This does two things. First it makes sure that your c.ExecuteScalar() isn't returning null If it did so and you tried to cast, you'd have problems.
Second, it makes casting much simpler because it can be applied to pretty much all cases when reading from a query.
The object becomes a string. If you want it as a string, you're done.
If you want it as a boolean, check to see if that string.Equals("true")
If you want it as an int, Int32.Parse(string);
if you want it as a long, Int64.Parse(string);
Basically, you won't have to worry about fully understanding overloading/explicit conversion.

Related

Using double.Parse with a null value

Below is my statement:
double? My_Value = null;
if (Request.Form["MyValue"] != null)
My_Value = double.Parse(Request.Form["MyValue"].ToString());
When I try to submit my form with no value for 'MyValue' I get a run time error saying 'Input string was not in a correct format.'. When I try to use:
My_Value = double.TryParse(Request.Form["MyValue"].ToString());
Visual Studio gives me a compile error that says 'No overload for method 'TryParse' takes 1 arguments'.
When I provide a value for 'My_Value', the form submits. How do I get the program to accept a null value? Thank you.
You need to declare a double variable to store the result and pass it to TryParse as an out argument, so it will be assigned if the parse succeeded:
double result;
var isValid = double.TryParse(Request.Form["MyValue"].ToString(), out result);
Also TryParse is different than Parse method, it doesn't return a numerical result, it returns a boolean result that indicates whether the parsing is succeeded or not.So you need to assign that result and check it's value to make sure parsing was successful.Or you could directly check the result without storing it in a variable.
double result;
double? My_Value = double.TryParse(Request.Form["MyValue"].ToString(), out result)
? (double?)result
: null;
Both solutions will result in 0;
string myString = null;
double result = Convert.ToDouble(myString);
OR
string myString = null;
double result = double.Parse(myString ?? "0");
The problem with your first case isn't just about handling nulls but rather about handling anything that cannot be parsed (since you are accepting a value from an untrustworthy source). Using TryParse is the way to go here.
However, the TryParse method accepts two arguments, the first the value to parse, the second a value to assign to if parsing succeeds (as an out) parameter.
For just such an occasion whereby you'd like a nullable result, a custom utility method can come in handy:
public static class NullableDouble
{
public static double? TryParse(string input)
{
double result;
var success = double.TryParse(input, out result);
return success ? result as double? : null;
}
}
Useable like so:
var myValue = NullableDouble.TryParse((Request.Form["MyValue"] ?? string.Empty).ToString());
The signature for TryParse is bool TryParse(string str, out double result)
Use it like this:
double result;
var success = double.TryParse(Request.Form["MyValue"].ToString(), out result);
My_Value = success? result : 0d;
As "usr" mentioned in the comments, the next time you get an error like this, you should check the MSDN documentation first before coming here.

why is this specified cast not valid??

i use the following code to map data from sql reader to C# Objects. the Power is of data type float in both code and sql database .. y is the cast error message occuring?
private Entity.PanelDetail MapDataReader(SqlDataReader dataReader)
{
Entity.PanelDetail panelDetail = new Entity.PanelDetail();
panelDetail.IdPanelDetail = DataReaderExtensions.GetStringOrNull(dataReader, "idPanelDetail");
panelDetail.IdDeviceDetail = DataReaderExtensions.GetStringOrNull(dataReader, "idDeviceDetail");
panelDetail.Power = DataReaderExtensions.GetFloatOrNull(dataReader, "Power");
panelDetail.Current = DataReaderExtensions.GetFloatOrNull(dataReader, "Current");
panelDetail.Length = DataReaderExtensions.GetFloatOrNull(dataReader, "Length");
panelDetail.Width = DataReaderExtensions.GetFloatOrNull(dataReader, "Width");
panelDetail.CreatedBy = DataReaderExtensions.GetStringOrNull(dataReader, "CreatedBy");
panelDetail.CreationDate = DataReaderExtensions.GetDateTimeOrNull(dataReader, "CreationDate");
panelDetail.ModifiedBy = DataReaderExtensions.GetStringOrNull(dataReader, "ModifiedBy");
panelDetail.ModifiedDate = DataReaderExtensions.GetDateTimeOrNull(dataReader, "ModifiedDate");
panelDetail.IsActive = DataReaderExtensions.GetBoolOrNull(dataReader, "IsActive");
panelDetail.IsDeleted = DataReaderExtensions.GetBoolOrNull(dataReader, "IsDeleted");
return panelDetail;
}
My guess that the value is being returned as a boxed double instead of float. Try to use
(float) dataReader.GetDouble(fieldOrdinal);
See Mapping CLR Parameter Data
I would make a good bet that the data type being return is actually a (boxed) double.
Update: Actually I just found that an SQL float maps to a .NET double on MSDN (so yes this is your problem): http://msdn.microsoft.com/en-us/library/ms131092.aspx
Try this as a test:
(float)dataReader.GetDouble(fieldOrdinal);
The reason is that SQL Float is double in .net. You can see the complete mapping here. Therefore, as others have suggested you need to read double and then try to cast it to float.
(float)dataReader.GetDouble("Power");

Handle nulls correctly

I have the following code -
int lat = System.Convert.ToInt16(latTextBox1.Text);
This is happening on a changed event.
However my code is breaking on this line saying -
Input string was not in a correct format.
Where latTextBox1.Text = "" which is an empty string.
I think this is breaking because it cannot convert an empty string into a null value.
How can I modify my code to account for null values?
OK, based on your comment you could use:
int? lat = string.IsNullOrEmpty(latTextBox1.Text)
? (int?)null : Convert.ToInt32(latTextBox1.Text);
int? is a nullable int.
How about a simple:
int? lat = null;
int dummyLat;
if (Int32.TryParse(latTextBox1.Text, out dummyLat)
lat = dummyLat;
On a side note:
I' never convert strings in the TextChanged event ever! Why? Because it triggers an event upon every keypress! Use some other trigger to initiated the conversion (for example a button).
Well, Convert.ToInt16 isn't meant to convert an empty string into a null value... indeed it can't, given that the return type is a non-nullable Int16 (aka short).
I suspect you actually want something more like:
int lat;
if (int.TryParse(latTextBox1.Text, out lat))
{
// Use lat
}
else
{
// Invalid or empty input. Handle appropriately.
}
If you want to handle empty strings differently to invalid input, you'll need to do that explicitly - although you should also consider whether "just whitespace" is equivalent to "empty" or "invalid".
You could use the following method:
Int16.TryParse:
Or you could check if the string is not null or empty before performing the logic:
if (!string.IsNullOrEmpty(latTextBox1.Text)) {
lat = System.Convert.ToInt16(latTextBox1.Text);
}
http://msdn.microsoft.com/en-us/library/system.int16.tryparse.aspx
you should first check that the current value is not an empty one before trying to convert it to an integer, kindly check out the following snippet
int lat = 0;
If(! string.IsNullorEmpty(latTextBox1.Text))
{
lat = System.Convert.ToInt32(latTextBox1.Text);
}
// use your lat variable here
Update:
From your comment above, lat may hold the NULL value, so you will have to make it a nullable Int in order to make it hold the value NULL
consider this updated code snippet
int? lat = 0;
If(! string.IsNullorEmpty(latTextBox1.Text))
{
lat.value = System.Convert.ToInt32(latTextBox1.Text);
}
// use your lat variable here by accessing the lat.value property
Note: latiture and longtitude values should be stored in a double datatype in order to preserve the precision.
You have to check for the string being set:
int lat = 0;
if (string.IsNullOrEmpty(latTextBox1.Text)
{
// Your null case here
}
else
{
lat = System.Convert.ToInt16(latTextBox1.Text);
}
Though:
int lat = 0;
if (!Int32.TryParse(latTextBox1.Text, out lat)
{
// Error handling here
}
is probably a better approach as it copes with non numeric input.
int lat = 0;
if (Int32.TryParse(laTextBox1.Text, out lat))
{
//success, textbox contained an int, now lat has the value of that int
}
else
{
//failure, textbox did not contain an int
}
int i = 0;
if (!Int32.TryParse(latTextBox1.Text, out i)) {
i = 0; // or default value;
}
One liner:
int lat = System.Convert.ToInt16(latTextBox1.Text.Length == 0 ? 0 : latTextBox1.Text);
Basically works like coalesce, if latTextBox1.Text does not have a value, set it to zero
otherwise the value from latTextBox1.Text

LinqToXML, breaking when Node doesn't exist. How do I check for existence?

var doc = XDocument.Parse(inputXML);
this bombs out when "amount" node is not present. How can I check for existence prior to evaluating?
decimal amt;
var amount = doc.Descendants("amount").SingleOrDefault().Value;
bool amountValid = decimal.TryParse(amount, out amt);
I need to make sure "amount" is available prior to evaluating.
Can anyone help?
Thanks All,
~ck in San Diego
XElement provides explicit casts for most value types, including Nullable<Decimal>:
var amt = (decimal?)doc.Descendants("amount").SingleOrDefault();
From there you can check if amt is null or use its HasValue property.
Update: It's worth pointing out that the cast will throw a FormatException if the value is not a Decimal. If you still want to use TryParse, you can keep the code simple with a string cast:
decimal amt;
var amount = (string)doc.Descendants("amount").SingleOrDefault();
bool amountValid = decimal.TryParse(amount, out amt);
Internally, the string cast is implemented like Ben's sample, returning either null or element.Value.
Try this:
var amountElement = doc.Descendants("amount").SingleOrDefault();
if (amountElement != null)
{
decimal amt;
bool amountValid = decimal.TryParse(amountElement.Value, out amt);
// other code
}

Better way to cast object to int

This is probably trivial, but I can't think of a better way to do it. I have a COM object that returns a variant which becomes an object in C#. The only way I can get this into an int is
int test = int.Parse(string.Format("{0}", myobject))
Is there a cleaner way to do this? Thanks
You have several options:
(int) — Cast operator. Works if the object already is an integer at some level in the inheritance hierarchy or if there is an implicit conversion defined.
int.Parse()/int.TryParse() — For converting from a string of unknown format.
int.ParseExact()/int.TryParseExact() — For converting from a string in a specific format
Convert.ToInt32() — For converting an object of unknown type. It will use an explicit and implicit conversion or IConvertible implementation if any are defined.
as int? — Note the "?". The as operator is only for reference types, and so I used "?" to signify a Nullable<int>. The "as" operator works like Convert.To____(), but think TryParse() rather than Parse(): it returns null rather than throwing an exception if the conversion fails.
Of these, I would prefer (int) if the object really is just a boxed integer. Otherwise use Convert.ToInt32() in this case.
Note that this is a very general answer: I want to throw some attention to Darren Clark's response because I think it does a good job addressing the specifics here, but came in late and wasn't voted as well yet. He gets my vote for "accepted answer", anyway, for also recommending (int), for pointing out that if it fails (int)(short) might work instead, and for recommending you check your debugger to find out the actual runtime type.
The cast (int) myobject should just work.
If that gives you an invalid cast exception then it is probably because the variant type isn't VT_I4. My bet is that a variant with VT_I4 is converted into a boxed int, VT_I2 into a boxed short, etc.
When doing a cast on a boxed value type it is only valid to cast it to the type boxed.
Foe example, if the returned variant is actually a VT_I2 then (int) (short) myObject should work.
Easiest way to find out is to inspect the returned object and take a look at its type in the debugger. Also make sure that in the interop assembly you have the return value marked with MarshalAs(UnmanagedType.Struct)
Convert.ToInt32(myobject);
This will handle the case where myobject is null and return 0, instead of throwing an exception.
Use Int32.TryParse as follows.
int test;
bool result = Int32.TryParse(value, out test);
if (result)
{
Console.WriteLine("Sucess");
}
else
{
if (value == null) value = "";
Console.WriteLine("Failure");
}
Maybe Convert.ToInt32.
Watch out for exception, in both cases.
var intTried = Convert.ChangeType(myObject, typeof(int)) as int?;
I am listing the difference in each of the casting ways. What a particular type of casting handles and it doesn't?
// object to int
// does not handle null
// does not handle NAN ("102art54")
// convert value to integar
int intObj = (int)obj;
// handles only null or number
int? nullableIntObj = (int?)obj; // null
Nullable<int> nullableIntObj1 = (Nullable<int>)obj; // null
// best way for casting from object to nullable int
// handles null
// handles other datatypes gives null("sadfsdf") // result null
int? nullableIntObj2 = obj as int?;
// string to int
// does not handle null( throws exception)
// does not string NAN ("102art54") (throws exception)
// converts string to int ("26236")
// accepts string value
int iVal3 = int.Parse("10120"); // throws exception value cannot be null;
// handles null converts null to 0
// does not handle NAN ("102art54") (throws exception)
// converts obj to int ("26236")
int val4 = Convert.ToInt32("10120");
// handle null converts null to 0
// handle NAN ("101art54") converts null to 0
// convert string to int ("26236")
int number;
bool result = int.TryParse(value, out number);
if (result)
{
// converted value
}
else
{
// number o/p = 0
}
There's also TryParse.
From MSDN:
private static void TryToParse(string value)
{
int number;
bool result = Int32.TryParse(value, out number);
if (result)
{
Console.WriteLine("Converted '{0}' to {1}.", value, number);
}
else
{
if (value == null) value = "";
Console.WriteLine("Attempted conversion of '{0}' failed.", value);
}
}
Strange, but the accepted answer seems wrong about the cast and the Convert in the mean that from my tests and reading the documentation too it should not take into account implicit or explicit operators.
So, if I have a variable of type object and the "boxed" class has some implicit operators defined they won't work.
Instead another simple way, but really performance costing is to cast before in dynamic.
(int)(dynamic)myObject.
You can try it in the Interactive window of VS.
public class Test
{
public static implicit operator int(Test v)
{
return 12;
}
}
(int)(object)new Test() //this will fail
Convert.ToInt32((object)new Test()) //this will fail
(int)(dynamic)(object)new Test() //this will pass
You can first cast object to string and then cast the string to int;
for example:
string str_myobject = myobject.ToString();
int int_myobject = int.Parse(str_myobject);
this worked for me.
int i = myObject.myField.CastTo<int>();
This worked for me, returning 0 also when myobject contains a DBNull
int i = myobject.ToString().Cast<int>().FirstOrDefault();

Categories

Resources