System.InvalidCastException: Specified cast is not valid. Error - c#

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

Related

My Table Adapter is returning null even after checking that the query is correct

I use a created query to return a row of values from a key, I have checked on the query executor but when running the program it is returning null. Please help me I'm starting to lose my mind.
I've tried debugging but the problem is coming from the fill data query and it is returning null.
// Add ref. to the Dataset
ViewMedia viewMediaSetInstance = new ViewMedia();
// Create an empty Table
ViewMedia.ViewMediaDataTable viewMediaTable = new ViewMedia.ViewMediaDataTable();
// Create the Adapter we are going to use to populate the Table
Model.ViewMediaTableAdapters.ViewMediaTableAdapter MediaTableAdapter = new Model.ViewMediaTableAdapters.ViewMediaTableAdapter();
//Use query
MediaTableAdapter.findByPublishYear(viewMediaTable, publishYear);
//It doesn't find the row
//I don't seem to find a solution even when the query returns the values in the executer.
//viewMediaTable.Rows.Count == null so doesn't get inside
if (viewMediaTable.Rows.Count > 0)
{
DataRow selectedUser = viewMediaTable.Rows[0];
media = new Media(Int32.Parse(selectedUser["MediaID"].ToString()), selectedUser["Title"].ToString(), Int32.Parse(selectedUser["PublishYear"].ToString()));
return media;
}
else
{
return null;
}
I'm expecting to return the row of data to display in a book display.
This is wonky; you've got strongly typed data rows with proper typed properties for everything, yet you're treating them as generic datarows with string column names, holding objects that you're tostring()ing and parsing. It was never intended to be used this way.
Your code should look more like this:
ViewMedia viewMediaSetInstance = new ViewMedia();
ViewMedia.ViewMediaDataTable viewMediaTable = new ViewMedia.ViewMediaDataTable();
Model.ViewMediaTableAdapters.ViewMediaTableAdapter MediaTableAdapter = new Model.ViewMediaTableAdapters.ViewMediaTableAdapter();
MediaTableAdapter.findByPublishYear(viewMediaTable, publishYear);
//don't need to access the .Rows property to get the count
if (viewMediaTable.Count > 0)
{
//don't need to access the .Rows property to get the data
ViewMediaRow selectedUser = viewMediaTable[0];
media = new Media(selectedUser.MediaID, selectedUser.Title, selectedUser.PublishYear);
return media;
}
else
{
return null;
}
I also disagree with your assertion in the code comments that datatable.Rows.Count is null. A datatable's .Count property is an integer regardless of whether a strongly or weakly typed datatable is in use; it can never be null
You don't need to create a dataset, if you enable creating a method that returns a datatable. Typically these methods are called GetDataByXXX and the fill methods are called FillByXXX (you've called your fill method findByPublishYear). It's configured on the following screen of the TA wizard:
image courtesy of nullskull.com
This can simplify your code to just the following (add a reference to Model.ViewMediaTableAdapters):
var mDT = new ViewMediaTableAdapter().GetDataByPublishYear(publishYear);
Media m = null;
if (mDT.Count > 0)
media = new Media(mDT[0].MediaID, mDT[0].Title, mDT[0].PublishYear);
return m;
Most critically here, DON'T access the first row via the .Rows collection (viewMediaDataTable.Rows[0]) because that returns a base type DataRow. Access it directly via the default property indexer on the strongly typed datatable (viewMediaDataTable[0]) as this will return an object of type ViewMediaRow which in turn has nicely named, typed properties for all the columns in the datatable
viewMediaDataTable[0].PublishYear; //ViewMediaRow is a strongly typed class that has this property as an int
viewMediaDataTable.Rows[0].PublishYear; //"DataRow does not contain a definition for 'PublishYear'"
Now, if any of the data items in the row is null and the setting of the column upon null is "throw exception" you will see an exception of type StrongTypingException- it happens when you have some column that is of a type that cannot be null (such as an int) but it's null because the database query didn't return a value for that row. You were hitting this with your code because som int column (for example) was DBNull.Value and the only thing a datarow will do whn you try to access an int column tha tis DBNull, is throw an exception. By specifying SELECT * in the query, you caused the query to return a value for the column; by not selecting a column the datatable will always treat it as null. You can still also encounter a strongtypingexception if the value of the data in the database is also null. In these cases, use the IsXXXNull() methods to determine if the property is null before trying to access it (causing a strongtypingexception)
Edit: Found the error, I was supposed to get all the columns from the query (using *) and then in the code take what I need otherwise null values get returned.

Can't use Distinct function with an NTEXT field in C# and LINQ

I have a field called Description in a table that is of the type NTEXT. My issue is that I need to use the method .Distinct() but am not able to as "The ntext data type cannot be selected as DISTINCT because it is not comparable."
There is another question very similar to this found here but the accepted solution does not work for me. When I try it I get a new error saying "Argument data type ntext is invalid for argument 1 of len function."
Below is the Linq statement I had originally and the one below it is what I tried to do after reading the answer to the other similar question.
return (from vl in db.ValueLog
join vc in db.ValueCodes on vl.ValueCode equals vc.ValueCode
select new ValueLogItem
{
ValueId = vl.ValueId ,
Description = vl.Description.Substring(0),
Quantity = vl.Quantity,
Code = vc.ValueCode
}).Distinct().ToList();
Does anyone have any ideas on how to get around this restriction besides just converting the field? Thanks!
I am well aware that NTEXT, TEXT, and IMAGE have all been deprecated since 2005, but I am not able to change the field's type at the moment as I do not have access to do that.
I am also well aware that NTEXT, TEXT, and IMAGE can't be made DISTINCT. I am trying to figure out a work around in LINQ. Doing it in SQL is extremely simple.
I am writing down the ways you can try to compare
First
Try GroupBy instead of Distinct. GroupBY works in similar way
Second
Convert the Description into Byte array and compare the arrays. For that, you can use
static bool ByteArrayCompare(byte[] a1, byte[] a2)
{
return StructuralComparisons.StructuralEqualityComparer.Equals(a1, a2);
}
or
return a1.SequenceEqual(b1);
or
public bool Equality(byte[] a1, byte[] b1)
{
int i;
if (a1.Length == b1.Length)
{
i = 0;
while (i < a1.Length && (a1[i]==b1[i])) //Earlier it was a1[i]!=b1[i]
{
i++;
}
if (i == a1.Length)
{
return true;
}
}
return false;
}
The basic issue is that TEXT, NTEXT, and IMAGE data fields are not allowed in a SELECT using DISTINCT. One of SQL Server's errors specifically states:
Server: Msg 421, Level 16, State 1, Line 1
The text/ntext/image data type cannot be selected
as DISTINCT because it is not comparable.
If you can't change the data type, you won't be able to use DISTINCT on that field. So, CAST/CONVERT the text field to VARCHAR(MAX) on the fly if you can't change the underlying data type.

DataTable Linq with two join statements in C#

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!)

Specified cast exception in LINQ query

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.

Specified cast is invalid error, LINQ to Oracle table

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.

Categories

Resources