New to Linq, so apologies if this is basic. This query is throwing up the error {"Cannot cast DBNull.Value to type 'System.Int64'. Please use a nullable type."} when I enumerate the results.
private void AddLevels(long rootid)
{
var results = from row in data.AsEnumerable()
where row.Field<long>("ParentID") == rootid
select row;
foreach (DataRow row in results)
{
//do stuff
}
}
The column ParentID does accept nulls - do I need to handle these separately?
EDIT2: Actual solution below that still uses Linq.
EDIT: I solved this by scrapping Linq and just using a DataTable.Select statement instead. If anyone's got input on the performance difference I'd be interested.
Use this line in your query:
where row.Field<decimal?>("ParentID") == rootid
decimal? is syntactic sugar for System.Nullable<decimal>, which is essentially the same as decimal, except that it also allows for null values.
long is a different type altogether -- it can only represent integers and not decimal values, hence the "Specified cast is not valid" error.
long rootid is nullable type? It should be then only it can accept nulls
Related
My code:
var Result = from TempRow in ArrAbsDiff
where TempRow.Strike == StrikeOfMinAbsDiff
select TempRow.PutMidPrice;
I know that the above code return just one value of type decimal (maybe double). However, Result is of type Enumerable and I could not easily write Result + 2. I need to convert it property. I can do it through the following code:
var Result = (from TempRow in ArrAbsDiff
where TempRow.Strike == StrikeOfMinAbsDiff
select TempRow.PutMidPrice).Min();
Is there more efficient way to accomplish it?
Regards,
I know that the above code return just one value of type decimal
Then use First method instaed of Min.
At compile time, it's unknown whether the query you have returns 1 record or more than 1 record. So, it assumes a list of them.
I don't know if there is a performance difference between them, I typically use .Single() to get the single record. It's more clear that I want a single record and not, for example, the minimum one.
Try using FirstOrDefault()" this selects the first result returned (as you know only one value will be returned). if a value is not returned the Result will be null, catch this in an if statement like below:
var Result = (from TempRow in ArrAbsDiff
where TempRow.Strike == StrikeOfMinAbsDiff
select TempRow.PutMidPrice).FirstOrDefault();
if (Result == null)
return; // or error message
this will also keep the type of value returned
(typed this of the top of my head, may need slight changes!)
Hope everybody is pretty good.
Well, I am getting a weird 'Specified Cast is not valid.' exception in one of my LINQ queries.
The code is as follows:
public string GetFiscalYearID(string fiscalYear)
{
int fYear = Convert.ToInt32(fiscalYear);
DataTable dtFiscalYearID = new DataTable();
dtFiscalYearID = DomainBL.GetDomainDataFromFieldName("FiscalYearId");
**var item = from r in dtFiscalYearID.AsEnumerable()
where r.Field<Int32>("FiscalYearNumber") == fYear
select r.Field<Int32>("FiscalYearId");**//Exception at this line
if (item.ToList().Count> 0)
{
return item.ToList()[0].ToString();
}
else
{
return string.Empty;
}
}
Here, dtFiscalYearID gets a DataTable from the DB which has just 2 columns namely, FiscalYearId and FiscalYearNumber. DataTypes of FiscalYearId and FiscalYearNumber are tinyint and smallint respectively.
When item is expanded, I see the Specified Cast exception, I tried Int16 too, but it too throws me an exception.
Can experts here tell me what might be wrong in the above code?
Any pointers or such will be quite appreciated.
Regards
Anurag
Try this:
select (int) r.Field<byte>("FiscalYearId")
tinyint is byte in c#, bytes can be casted to int directly
EDIT:
According to this list: MSDN mapping CLR parameter list, tinyint is mapped to Byte. I think that line with where is also corrupted cause you are trying to convert smallint to int32.
where r.Field<Int16>("FiscalYearNumber") == fYear
Int16 is equivalent to smallint.
I am on a C# ASP.NET project.
I have a MySQL table with a userid field of type int.
Now I want to get the number of rows where value of userid equals certain value using LINQ.
To achieve this, I wrote the following method:
public int getCount(int usercode) {
int count = 0;
DataTable mytable = getAllRowsAndReturnAsDataTable(); // assigning a DataTable value to mytable.
if (mytable.Rows.Count > 0) {
count = (from x in mytable.AsEnumerable() where x.Field<Int32>("userid") == usercode select x).Count();
}
return count;
}
but it is showing error System.InvalidCastException: Specified cast is not valid. showing count = (from x in mytable.AsEnumerable() where x.Field<Int32>("userid") == usercode select x).Count(); in red highlight area.
I don't know what I did wrong here. Please help.
The most likely cause of the InvalidCastException is the x.Field<Int32>("userid") line. The Field<T> extension method will throw an InvalidCastException in the case where the actual type of the data doesn't match the type which was passed to Field<T>. Hence if userid wasn't an Int32 this would throw.
EDIT
Based on your comments the type of userid is actually UInt32 and not Int32. This is what is causing the problem. Try using the following and it should work
x.Field<UInt32>("userid")
Without looking at the data coming back from your database I can only guess that the following part of your LINQ is at fault:
x.Field<Int32>("userid")
Your userid column value probably isn't an int, I would put my money on it being NULL?
UPDATE: Can you confirm it's not the Field call that is breaking? Simply change your code to something like this without the Field call:
public int getCount(int usercode){
int count = 0;
DataTable mytable = getAllRowsAndReturnAsDataTable(); // assigning a DataTable value to mytable.
if (mytable.Rows.Count > 0) {
count = mytable.AsEnumerable().Count(); // No WHERE function call so no casting.
}
return count;
}
You could also inspect what the values are that are returned by mytable.AsEnumerable() in a watch window for example to ensure that everything looks correct. If the code above works then it's the Field call blowing up. Find out which row cannot be cast to an Int32 and go from there.
If it is in fact NULL, there are a number of ways you can solve this.
Make sure you don't return NULL from your database query, in MySQL you can use IFNULL.
Use a nullable type for the generic being passed into Field:
where x.Field("userid") == (Int32?)usercode
Oracle column: user_id int not null,
Linq query:
UserId = user.Field<int>("user_id"),
UserId is int type. Other string, char fields are workign fine, only when I use thsi field I get this error.
What is the correct mapping or anythign I am doing wrong ?
If you're using Field<T>() then that suggests you're using a DataTable, at which point the database type is mostly irrelevant. The exception should show you how the cast has failed - what the actual type is. If it doesn't, you can easily put some diagnostics in though:
object o = user["user_id"];
if (o == null)
{
Console.WriteLine("user_id is null");
}
else
{
Console.WriteLine("Actual type of user_id: {0}", o.GetType());
}
I suspect you'll find it's long or short, or something like that - but this should show you for sure.
I have two objects declared as IEnumerable<DateTime> xVal and IEnumerable<double> yVal.
Then some where is my program I have:
var xVals = from p in result where p.chemical == "Benzene" select p.SampDate_Name;
var yVals = from p in result where p.chemical == "Benzene" select p.PCL;
Then I am trying to the following assignment:
xVal = xVals as IEnumerable<DateTime>;
yVal = yVals as IEnumerable<double>;
And the above code sets xVal and yVal to null.
Could anybody explain what is wrong here? I would very much appreciate the help.
Thanks.
One thing is certain: The input is not null. So xVals and yVals are non-null as debugged by me. I am also able to loop through them to get the content of each.
I will try the other suggestions when I get back and post my findings. Thanks a lot folks for your replies.
The problem here was that LINQ is executed lazy, It will be executed when you do either foreach or ToList/ToArray/ToDictionary. The two linq queries in my code were not executed before the assignment was done. Consequently xVal and yVal were set to null.
Thanks for all the help.
The as keyword will set the output to null if the input was null or the cast could not be carried out.
If you used xVal = (IEnumerable<DateTime>)xVals you would probably get an exception saying that it could not be cast.
MSDN description for as keyword
If you have a generic collection, to get it to IEnumerable, try .AsEnumerable(). So your new code...
xVal = xVals.AsEnumerable();
yVal = yVals.AsEnumerable();
The as keyword doesn't actually do a cast, but does conversions between related reference types. So if you have a concrete type, you could treat assign it to a new variable with a type of the base class using as. If the types are not compatible, then as will return null. This is a good way to do type checking without having to worry about exceptions. Instead you can perform a null check on the result of the conversion.
It's hard to tell what types p.SampDate_Name and p.PCL are, but I would guess strings? If so you can add the cast to the select statement.
var xVals = from p in result where p.chemical == "Benzene" select DateTime.Parse(p.SampDate_Name);
var yVals = from p in result where p.chemical == "Benzene" select Double.Parse(p.PCL);