why is this specified cast not valid?? - c#

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");

Related

Type does not contain definition of 'Round' and 'Parse'

I get this strange error and it doesn't compile. My code looks like this:
if (model.CreditType == "Extra")
{
decimal num1 = decimal.Parse(amountReturn.ToString()) / model.CreditPeriod;
((dynamic)base.ViewBag).MonthlyPayment = Math.Round(num1, 2,
MidpointRounding.AwayFromZero);
dynamic viewBag = base.ViewBag;
Type type = typeof(Math);
decimal num2 = num1;
Type type1 = typeof(decimal);
viewBag.MonthlyPaymentWithTax = type.Round(num2 +
type1.Parse(((dynamic)base.ViewBag).TaxToAdd.ToString()) /
model.CreditPeriod, 2, 1);
}
I will be very thankful if somebody explains me how to fix my problem. On compile it generates the following errors.
Thank you in advance!
I don't know asp.net but I think I could explain about your error.
When you use typeof(myobj) this expression returns an instance of System.Type, not a same of referencing type itself in code, like Int.Parse().
An instance of System.Type is representation of runtime type information. It's a kind of "meta" object, not same as referencing the type you want on code.
It you wish to call a specific method via System.Type object, you should find it first. This method of calling is called as "Reflection". I recommend you to not do this because it is not easy, needs boilerplate(?) and not needed in most time when you know your type. doc
I just recommend first cast your target type and just call the static method of type (like the other answer did). or use TryParse?
(code is not tested for compilation)
dynamic a = "123";
string a_casted = 123 as string;
if (a_casted == null) { return; }
int a_parsed = Int.Parse(a_casted);
As mentioned in the error, the Type doesn't contain a definition for both Round and Parse. You need to use Decimal.Parse and Decimal.Round instead
You need to use
viewBag.MonthlyPaymentWithTax = Decimal.Round(num2 +
Decimal.Parse(((dynamic)base.ViewBag).TaxToAdd.ToString()) /
model.CreditPeriod, 2);
You can read more on both methods here
Decimal.Round
Decimal.Parse

Is there any way to create a function that can change the data type of a variable?

I 'm new to C#. Is there any way to create a function that can change the datatype of a variable to an another datatype and return the changed value.
I don't want to use the built-in Convert class.
For example :
Let's assume that ChangeDataType is the name of the function. It should also be possible to do the same thing with all datatypes.
int a = 5;
float b = ChangeDataType(a, "float"); // 5.0
Thanks.
Please note that you cannot change data type of already declared variable. But you can create new variable of desired type and then typecast old variable into new one. If this type casting fails, then invalidcastexception is thrown.
Below are different kinds of typecasting options:
1. Implicit Type casting
In this you don't need to use any syntax.
For ex:
int i = 10;
float a = i;
2. Explicit Type casting
You need to specify the type in which you want to convert to. For ex:
class Test
{
static void Main()
{
double x = 1234.7;
int a;
// Cast double to int.
a = (int)x;
System.Console.WriteLine(a);
}
}
// Output: 1234
3. User Defined Casts
Using implict and explicit keywords in c#.
Please refer
4. Helper Classes
There are many classes which provides method to convert data types.
One of the important class is - Convert.
This class provides a lot of methods. Convert.ToString, Convert.ToInt32, etc.
Another example is TryParse methods in int, long, double, DateTime, etc classes. Please refer

Function is being called with type in front of it: (T)func(param1, param2). What is this called and what is it for?

Function is being called with type in front of it: (T)func(param1, param2). What is this called and what is it for? I'd assume it's coercing a return type?
Again, the pattern takes the form:
(T)func(params)
example:
(int)Mathf.Log(level, 2f) // it's an example from unity, level is of type int
The (T) is an explicit cast. See the docs here, under the "Explicit Conversions" title: https://msdn.microsoft.com/en-us/library/ms173105.aspx
The func(params) bit is just a method call. The cast is not part of it, you're just casting the result.
// cast the result of a method call
var i = (int)Mathf.Log(level, 2f);
// cast a random object
var s = (string)someObject;
It's not a pattern per se (depending on what exactly you mean by "pattern")... it's just C#. It sounds like maybe you're confused by the fact that it appears a method is being converted to a primitive type?
What it's actually doing is converting the return type of Mathf.Log (a float) to an int.
So this:
int log = (int)Mathf.Log(level, 2f);
Is equivalent to this:
float result = Mathf.Log(level, 2f);
int log = (int)result;
It's simply a cast ; Math.Log returns a double so a cast is needed to make it an int (truncating the result)

casting ExecuteScalar() result 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.

Invalid cast exception when reading result from SQLDataReader

My stored procedure:
#UserName nvarchar(64),
AS
BEGIN
SELECT MPU.UserName, SUM(TS.Monday)as Monday //TS.Monday contains float value
FROM dbo.MapTask MT JOIN dbo.MapPU MPU
ON MPU.ID = MT.MPUID
JOIN dbo.TimeSheet TS
ON MT.TMSID = TS.ID
WHERE MT.StartDate = #StartDate_int and MPU.UserName = #UserName
GROUP BY MPU.UserName
END
In my C# code
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
float monday = (float)reader["Monday"]; // Invalid cast exception
}
Can somebody tell me what I did wrong ? Thank you.
My guess is that the value is being returned as a boxed double instead of float. When you unbox the type has to be exactly right. So assuming I'm right and it's not decimal or something like that, you could use:
float monday = (float) (double) reader["Monday"];
and it would work. That's pretty ugly though. If you use SqlDataReader.GetFloat it should get it right if it's genuinely a single-precision value, and it's clearer (IMO) what's going on.
On the other hand, your data could actually be coming back from the database as a double, in which case you should (IMO) use:
float monday = (float) reader.GetDouble(column);
As an aside, are you sure that float is actually the most appropriate type here in the first place? Often decimal is more appropriate...
A sql float is a .NET Double, see on the msdn.
Try casting to a double.
I also had a similar issue and ended up doing this:
if (!oDR.IsDBNull(0))
Rating = (float)oDR.GetSqlDecimal(0).Value;
oDR.GetFloat(0) was returning and invalid cast exception when accessing the result of a SELECT AVG(...).
HTH
float monday = Convert.ToDouble(reader["Monday"]);
would be a nice approach. I am trying to find a solution for over an hour and it fails here. now it works fine.

Categories

Resources