Specified cast exception in LINQ query - c#

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.

Related

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.

System.InvalidCastException: Specified cast is not valid. Error

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

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.

Linq to DataTable - Cannot cast DBNull

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

Int32.TryParse() or (int?)command.ExecuteScalar()

I have a SQL query which returns only one field - an ID of type INT.
And I have to use it as integer in C# code.
Which way is faster and uses less memory?
int id;
if(Int32.TryParse(command.ExecuteScalar().ToString(), out id))
{
// use id
}
or
int? id = (int?)command.ExecuteScalar();
if(id.HasValue)
{
// use id.Value
}
or
int? id = command.ExecuteScalar() as int?;
if(id.HasValue)
{
// use id.Value
}
The difference between the three performance wise is negligible. The bottleneck is moving the data from the DB to your app, not a trivial cast or method call.
I would go with:
int? id = (int?)command.ExecuteScalar();
if(id.HasValue)
{
// use id.Value
}
It fails earlier, if one day people change the command to return a string or a date, at least it will crash and you will have a chance to fix it.
I would also just go with a simple int cast IF I always expected the command to return a single result.
Note, I usually prefer returning an out param than doing the execute scalar, execute scalar feels fragile (the convention that the first column in the first row is a return value does not sit right for me).
If you expect the command to return null, you should keep in mind that database null (DBNull) is not the same as .NET null. So, conversion of DBNull to int? would fail.
I'd suggest the following:
object result = command.ExecuteScalar();
int? id = (int?)(!Convert.IsDBNull(result) ? result : null);
If none of the above works (especially for users who are battling with MySQL)
why don't you try the following?
int id = Convert.ToInt32(cmd.ExecuteScalar().ToString());
int Result = int.Parse(Command.ExecuteScalar().ToString());
will work in C#.
The latter. Convert.ToInt32() is also an option.
Use id.HasValue for maximum Nullable Type cool-factor!
if ((Int32)cmd.ExecuteScalar () ** 1) //en esta parece qu esta el error pero no lo veo
{
Response.Redirect("Default.aspx");
}
else
{
Response.Redirect("error.htm") ;
}

Categories

Resources