SQL Tinyint / LINQ / cast not valid - please help

X

xlar54

Having a problem with code such as:

var dr1 = ds.Tables[1].AsEnumerable();
var dr2 = ds.Tables[2].AsEnumerable();

var dr3 = from t1 in dr1
join t2 in dr2 on t1.Field<int>("key1")
equals t2.Field<int>("key1") into g
from t2 in g.DefaultIfEmpty()
select new Batch
{
...
MyData = t2 == null ? 0 :
t2.Field<int>("some_tinyint_field"),

The problem is around the tinyint field. No matter what I change the
cast to, be it byte, int, I keep getting a "Specified cast not
valid". Does the Field<> method not like tinyints?
 
F

Frans Bouma [C# MVP]

xlar54 said:
Having a problem with code such as:

var dr1 = ds.Tables[1].AsEnumerable();
var dr2 = ds.Tables[2].AsEnumerable();

var dr3 = from t1 in dr1
join t2 in dr2 on t1.Field<int>("key1")
equals t2.Field<int>("key1") into g
from t2 in g.DefaultIfEmpty()
select new Batch
{
...
MyData = t2 == null ? 0 :
t2.Field<int>("some_tinyint_field"),

The problem is around the tinyint field. No matter what I change the
cast to, be it byte, int, I keep getting a "Specified cast not
valid". Does the Field<> method not like tinyints?

Likely the field is null, so the value is DbNull.Value, which isnt'
castable to whatever value type you cast it to. I'd suggest to create a
different extension method and use that instead of the Field<T>
extension method as it's pretty lame. See my .Value method below

/// <summary>
/// Gets the value of the column with the column name specified from the
DataRow in the type specified. If the value is DBNull.Value, null / Nothing
/// will be returned, if TValue is a nullable value type or a reference
type, the default value for TValue will be returned otherwise.
/// </summary>
/// <typeparam name="TValue">The type of the value.</typeparam>
/// <param name="row">The row.</param>
/// <param name="columnName">Name of the column.</param>
/// <returns>the value of the column specified, or the default value for
the type specified if not found.</returns>
/// <remarks>Use this method instead of Field(Of TValue) if you don't
want to receive cast exceptions</remarks>
public static TValue Value<TValue>(this DataRow row, string columnName)
{
TValue toReturn = default(TValue);
if(!((row == null) || string.IsNullOrEmpty(columnName) || (row.Table ==
null) || !row.Table.Columns.Contains(columnName)))
{
object columnValue = row[columnName];
if(columnValue != DBNull.Value)
{
Type destinationType = typeof(TValue);
if(typeof(TValue).IsNullableValueType())
{
destinationType = destinationType.GetGenericArguments()[0];
}
toReturn = (TValue)Convert.ChangeType(columnValue, destinationType);
}
}
return toReturn;
}

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
J

Jeroen Mostert

Frans said:
xlar54 said:
Having a problem with code such as:

var dr1 = ds.Tables[1].AsEnumerable();
var dr2 = ds.Tables[2].AsEnumerable();

var dr3 = from t1 in dr1
join t2 in dr2 on t1.Field<int>("key1")
equals t2.Field<int>("key1") into g
from t2 in g.DefaultIfEmpty()
select new Batch
{
...
MyData = t2 == null ? 0 :
t2.Field<int>("some_tinyint_field"),

The problem is around the tinyint field. No matter what I change the
cast to, be it byte, int, I keep getting a "Specified cast not
valid". Does the Field<> method not like tinyints?

Likely the field is null, so the value is DbNull.Value, which isnt'
castable to whatever value type you cast it to.

But .Field<>() doesn't just cast, and .Field<byte?>() should work.
 
M

Michael C

Frans Bouma said:
Likely the field is null, so the value is DbNull.Value, which isnt'
castable to whatever value type you cast it to. I'd suggest to create a
different extension method and use that instead of the Field<T> extension
method as it's pretty lame. See my .Value method below

Your function ignores a range of errors which is not a good thing.

Michael
 
X

xlar54

Having a problem with code such as:

                    var dr1 = ds.Tables[1].AsEnumerable();
                    var dr2 = ds.Tables[2].AsEnumerable();

                    var dr3 = from t1 in dr1
                              join t2 in dr2 on t1.Field<int>("key1")
equals t2.Field<int>("key1") into g
                              from t2 in g.DefaultIfEmpty()
                              select new Batch
                              {
                                  ...
                                      MyData = t2 == null ? 0 :
t2.Field<int>("some_tinyint_field"),

The problem is around the tinyint field.  No matter what I change the
cast to, be it byte, int, I keep getting a "Specified cast not
valid".  Does the Field<> method not like tinyints?

Thanks for the info. But this was the only one I could find that
would work:

MyData = t2 == null ? 0 : Int16.Parse(t2["some_tinyint_field"].ToString
()),
 
X

xlar54

Your function ignores a range of errors which is not a good thing.

Michael

I wasnt asking about a range of errors, I was asking how to solve that
specific problem. If you look at the code, it's been heavily modified
to just show the problem.
 
F

Frans Bouma [C# MVP]

Michael said:
Your function ignores a range of errors which is not a good thing.

And which range of errors might that be which aren't thrown by
exceptions already?

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
F

Frans Bouma [C# MVP]

xlar54 said:
Having a problem with code such as:

var dr1 = ds.Tables[1].AsEnumerable();
var dr2 = ds.Tables[2].AsEnumerable();

var dr3 = from t1 in dr1
join t2 in dr2 on t1.Field<int>("key1")
equals t2.Field<int>("key1") into g
from t2 in g.DefaultIfEmpty()
select new Batch
{
...
MyData = t2 == null ? 0 :
t2.Field<int>("some_tinyint_field"),

The problem is around the tinyint field. No matter what I change the
cast to, be it byte, int, I keep getting a "Specified cast not
valid". Does the Field<> method not like tinyints?

Thanks for the info. But this was the only one I could find that
would work:

MyData = t2 == null ? 0 : Int16.Parse(t2["some_tinyint_field"].ToString
()),

Did or didn't my function solve your problem?

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
F

Frans Bouma [C# MVP]

Jeroen said:
Frans said:
xlar54 said:
Having a problem with code such as:

var dr1 = ds.Tables[1].AsEnumerable();
var dr2 = ds.Tables[2].AsEnumerable();

var dr3 = from t1 in dr1
join t2 in dr2 on t1.Field<int>("key1")
equals t2.Field<int>("key1") into g
from t2 in g.DefaultIfEmpty()
select new Batch
{
...
MyData = t2 == null ? 0 :
t2.Field<int>("some_tinyint_field"),

The problem is around the tinyint field. No matter what I change the
cast to, be it byte, int, I keep getting a "Specified cast not
valid". Does the Field<> method not like tinyints?
Likely the field is null, so the value is DbNull.Value, which
isnt' castable to whatever value type you cast it to.

But .Field<>() doesn't just cast, and .Field<byte?>() should work.

It's been a while since I've written the code, but if I do recall
correctly I wrote it to avoid precisely the issue posted by TS. Though
it might be TS has a different cause for the same exception not sure.
What I do know is that for my purposes (datatable consuming code) I
couldn't get .Field<T> to work in all cases and needed the extension method.

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
M

Michael C

Frans Bouma said:
And which range of errors might that be which aren't thrown by exceptions
already?

Well, for a start, if they pass in a null row the person using your function
does not get an exception.

Michael
 
F

Frans Bouma [C# MVP]

Michael said:
Well, for a start, if they pass in a null row the person using your function
does not get an exception.

Correct, they get null back, which is the value for 'undefined'.

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
M

Michael C

Frans Bouma said:
Correct, they get null back, which is the value for 'undefined'.

That is not good, if they pass in no row they should get an exception.

Michael
 
F

Frans Bouma [C# MVP]

Michael said:
That is not good, if they pass in no row they should get an exception.

And when will that happen, exactly? Remember, this extension method is
used to retrieve data from a row, which you likely only obtain through
looping.

I disagree that they should get an exception, undefined is undefined.
Getting a value from an undefined object is undefined. But some might
think it should lead to an exception, I personally think that's not a
good way to go here.

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
M

Michael C

Frans Bouma said:
And when will that happen, exactly? Remember, this extension method is
used to retrieve data from a row, which you likely only obtain through
looping.

It could happen in many situations. If the programmer does something wrong
then they need to know about it, not have the problem ignored.
I disagree that they should get an exception, undefined is undefined.
Getting a value from an undefined object is undefined. But some might
think it should lead to an exception, I personally think that's not a good
way to go here.

You don't really say anything here except that you disagree. The standard
programming behaviour in dot net is that if you pass something invalid into
a function then an exception should be raised. You need a *good* reason to
ignore this behaviour but you don't seem to have a reason at all. This is
especially true on a function such as yours for 2 reasons, the first is that
it is a general purpose function and the second is that it is obviously
designed to replace/enhance a framework function which would have the
behaviour I described. What you end up with is a function that is
inconsistant with the rest of the framework and would catch many programmers
out. Instead of them getting an exception during testing they get a subtle
bug where some values are empty. This is obviously a lot harder to test
(it's pretty hard to ignore an exception) and the likelyhood of a bug
getting through to the user is much higher. Also, in the event that the bug
does get through to the user then it is *much* harder for you to track down
because instead of having a nice simple callstack which tells you the exact
location of the problem, you just get odd behaviour with no obvious cause.

Michael
 
E

Ed Haack

I found a very cool way, that may or may not help to detect nulls in
your datatable or what-have-you...

Here's an example:

DataTable dtResults = DataAccess.GetAllFromEmail();
var linqSample = from c in dtResults.AsEnumerable()
where !c.IsNull("isSuccess") &&
c.Field<bool>("isSuccess") == true
select new { To = c.Field<string>("toEmail"), From =
c.Field<string>("fromEmail"), Message = c.Field<string>("Message") };


The key here is in the where clause, !c.IsNull("columnName")

Hope this was helpful...
 
O

Oleg Usmanaev

I make next way
select *,CAST (your_tiny as int) you2 from .....
it is possilbe convert(int,your_tiny)
as You may see, i just converted field in sql
I have not found path to resolve this problen in asp code



Frans Bouma [C# MVP] wrote:

Re: SQL Tinyint / LINQ / cast not valid - please help
14-Mar-09

xlar54 wrote

Likely the field is null, so the value is DbNull.Value, which isnt'
castable to whatever value type you cast it to. I'd suggest to create a
different extension method and use that instead of the Field<T>
extension method as it's pretty lame. See my .Value method belo

/// <summary
/// Gets the value of the column with the column name specified from the
DataRow in the type specified. If the value is DBNull.Value, null / Nothin
/// will be returned, if TValue is a nullable value type or a reference
type, the default value for TValue will be returned otherwise
/// </summary
/// <typeparam name="TValue">The type of the value.</typeparam
/// <param name="row">The row.</param
/// <param name="columnName">Name of the column.</param
/// <returns>the value of the column specified, or the default value for
the type specified if not found.</returns
/// <remarks>Use this method instead of Field(Of TValue) if you don't
want to receive cast exceptions</remarks
public static TValue Value<TValue>(this DataRow row, string columnName

TValue toReturn = default(TValue)
if(!((row == null) || string.IsNullOrEmpty(columnName) || (row.Table ==
null) || !row.Table.Columns.Contains(columnName))

object columnValue = row[columnName]
if(columnValue != DBNull.Value

Type destinationType = typeof(TValue)
if(typeof(TValue).IsNullableValueType()

destinationType = destinationType.GetGenericArguments()[0]

toReturn = (TValue)Convert.ChangeType(columnValue, destinationType)


return toReturn


F

--
-----------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NE
LLBLGen Pro website: http://www.llblgen.co
My .NET blog: http://weblogs.asp.net/fboum
Microsoft MVP (C#
------------------------------------------------------------------------

Previous Posts In This Thread:

Re: SQL Tinyint / LINQ / cast not valid - please help
xlar54 wrote

Likely the field is null, so the value is DbNull.Value, which isnt'
castable to whatever value type you cast it to. I'd suggest to create a
different extension method and use that instead of the Field<T>
extension method as it's pretty lame. See my .Value method belo

/// <summary
/// Gets the value of the column with the column name specified from the
DataRow in the type specified. If the value is DBNull.Value, null / Nothin
/// will be returned, if TValue is a nullable value type or a reference
type, the default value for TValue will be returned otherwise
/// </summary
/// <typeparam name="TValue">The type of the value.</typeparam
/// <param name="row">The row.</param
/// <param name="columnName">Name of the column.</param
/// <returns>the value of the column specified, or the default value for
the type specified if not found.</returns
/// <remarks>Use this method instead of Field(Of TValue) if you don't
want to receive cast exceptions</remarks
public static TValue Value<TValue>(this DataRow row, string columnName

TValue toReturn = default(TValue)
if(!((row == null) || string.IsNullOrEmpty(columnName) || (row.Table ==
null) || !row.Table.Columns.Contains(columnName))

object columnValue = row[columnName]
if(columnValue != DBNull.Value

Type destinationType = typeof(TValue)
if(typeof(TValue).IsNullableValueType()

destinationType = destinationType.GetGenericArguments()[0]

toReturn = (TValue)Convert.ChangeType(columnValue, destinationType)


return toReturn


F

--
-----------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NE
LLBLGen Pro website: http://www.llblgen.co
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------

Re: SQL Tinyint / LINQ / cast not valid - please help
Frans Bouma [C# MVP] wrote:

But .Field<>() does not just cast, and .Field<byte?>() should work.

--
J.

Re: SQL Tinyint / LINQ / cast not valid - please help
Your function ignores a range of errors which is not a good thing.

Michael

SQL Tinyint / LINQ / cast not valid - please help
Having a problem with code such as:

var dr1 = ds.Tables[1].AsEnumerable();
var dr2 = ds.Tables[2].AsEnumerable();

var dr3 = from t1 in dr1
join t2 in dr2 on t1.Field<int>("key1")
equals t2.Field<int>("key1") into g
from t2 in g.DefaultIfEmpty()
select new Batch
{
...
MyData = t2 == null ? 0 :
t2.Field<int>("some_tinyint_field"),

The problem is around the tinyint field. No matter what I change the
cast to, be it byte, int, I keep getting a "Specified cast not
valid". Does the Field<> method not like tinyints?

Re: SQL Tinyint / LINQ / cast not valid - please help
able();
able();
2 on t1.Field<int>("key1")
DefaultIfEmpty()
tch
=A0 MyData =3D t2 =3D=3D null ? 0 :

Thanks for the info. But this was the only one I could find that
would work:

MyData =3D t2 =3D=3D null ? 0 : Int16.Parse(t2["some_tinyint_field"].ToStri=
ng
()),

Re: SQL Tinyint / LINQ / cast not valid - please help
on

I wasnt asking about a range of errors, I was asking how to solve that
specific problem. If you look at the code, it is been heavily modified
to just show the problem.

Re: SQL Tinyint / LINQ / cast not valid - please help
Michael C wrote:

And which range of errors might that be which aren't thrown by
exceptions already?

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------

Re: SQL Tinyint / LINQ / cast not valid - please help
xlar54 wrote:

Did or didn't my function solve your problem?

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------

Re: SQL Tinyint / LINQ / cast not valid - please help
Jeroen Mostert wrote:

It's been a while since I've written the code, but if I do recall
correctly I wrote it to avoid precisely the issue posted by TS. Though
it might be TS has a different cause for the same exception not sure.
What I do know is that for my purposes (datatable consuming code) I
couldn't get .Field<T> to work in all cases and needed the extension method.

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------

Re: SQL Tinyint / LINQ / cast not valid - please help
Well, for a start, if they pass in a null row the person using your function
does not get an exception.

Michael

Re: SQL Tinyint / LINQ / cast not valid - please help
Michael C wrote:

Correct, they get null back, which is the value for 'undefined'.

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------

Re: SQL Tinyint / LINQ / cast not valid - please help
That is not good, if they pass in no row they should get an exception.

Michael

Re: SQL Tinyint / LINQ / cast not valid - please help
Michael C wrote:

And when will that happen, exactly? Remember, this extension method is
used to retrieve data from a row, which you likely only obtain through
looping.

I disagree that they should get an exception, undefined is undefined.
Getting a value from an undefined object is undefined. But some might
think it should lead to an exception, I personally think that's not a
good way to go here.

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------

Re: SQL Tinyint / LINQ / cast not valid - please help

It could happen in many situations. If the programmer does something wrong
then they need to know about it, not have the problem ignored.


You don't really say anything here except that you disagree. The standard
programming behaviour in dot net is that if you pass something invalid into
a function then an exception should be raised. You need a *good* reason to
ignore this behaviour but you don't seem to have a reason at all. This is
especially true on a function such as yours for 2 reasons, the first is that
it is a general purpose function and the second is that it is obviously
designed to replace/enhance a framework function which would have the
behaviour I described. What you end up with is a function that is
inconsistant with the rest of the framework and would catch many programmers
out. Instead of them getting an exception during testing they get a subtle
bug where some values are empty. This is obviously a lot harder to test
(it's pretty hard to ignore an exception) and the likelyhood of a bug
getting through to the user is much higher. Also, in the event that the bug
does get through to the user then it is *much* harder for you to track down
because instead of having a nice simple callstack which tells you the exact
location of the problem, you just get odd behaviour with no obvious cause.

Michael


Submitted via EggHeadCafe - Software Developer Portal of Choice
Get Silverlight 4 Installed: Tips and Tricks
http://www.eggheadcafe.com/tutorial...b-f54c56a64ed9/get-silverlight-4-install.aspx
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top