convert tinyint to boolean

T

tshad

I have a value in my sql table set to tinyint (can't set to bit).

I am trying to move it into a boolean field in my program and have tried:

isTrue = (int)dbReader["IsTrue"]

and

isTrue = Convert.ToBoolean((int)dbReader["IsTrue"])

Both give me a "Specified cast is not valid".

Is there a simple way to do this other then

isTrue = false
if ((int)dbReader["IsTrue"] == 1)
isTrue = true;

Thanks,

Tom
 
T

tshad

tshad said:
I have a value in my sql table set to tinyint (can't set to bit).

I am trying to move it into a boolean field in my program and have tried:

isTrue = (int)dbReader["IsTrue"]

and

isTrue = Convert.ToBoolean((int)dbReader["IsTrue"])

Both give me a "Specified cast is not valid".

Is there a simple way to do this other then

isTrue = false
if ((int)dbReader["IsTrue"] == 1)
isTrue = true;

Turns out I can't do

if ((int)dbReader["IsTrue"] == 1)

or

if (((int)dbReader["IsTrue"]) == 1)

I still get the same error.

Yet, the debugger shows the value to be 1.

Thanks,

Tom
 
T

tshad

Tom Dacon said:
How about:

isTrue = (dbReader("IsTrue") <> 0

Actually, it would be something like:

isTrue = (int)dbReader["IsTrue"] != 0;

or

isTrue = ((int)dbReader["IsTrue"]) != 0;

but I get the same error.

Thanks,

tom
Tom Dacon
Dacon Software Consulting

tshad said:
I have a value in my sql table set to tinyint (can't set to bit).

I am trying to move it into a boolean field in my program and have tried:

isTrue = (int)dbReader["IsTrue"]

and

isTrue = Convert.ToBoolean((int)dbReader["IsTrue"])

Both give me a "Specified cast is not valid".

Is there a simple way to do this other then

isTrue = false
if ((int)dbReader["IsTrue"] == 1)
isTrue = true;

Thanks,

Tom
 
I

Ignacio Machin ( .NET/ C# MVP )

How about:
isTrue = (dbReader("IsTrue") <> 0

Actually, it would be something like:

isTrue = (int)dbReader["IsTrue"] != 0;

or

isTrue = ((int)dbReader["IsTrue"]) != 0;

but I get the same error.

Thanks,

tom




Tom Dacon
Dacon Software Consulting
tshad said:
I have a value in my sql table set to tinyint (can't set to bit).
I am trying to move it into a boolean field in my program and have tried:
isTrue = (int)dbReader["IsTrue"]
and
isTrue = Convert.ToBoolean((int)dbReader["IsTrue"])
Both give me a "Specified cast is not valid".
Is there a simple way to do this other then
isTrue = false
if ((int)dbReader["IsTrue"] == 1)
   isTrue = true;
Thanks,
Tom- Hide quoted text -

- Show quoted text -

what error r u getting?
 
I

Ignacio Machin ( .NET/ C# MVP )

I have a value in my sql table set to tinyint (can't set to bit).

I am trying to move it into a boolean field in my program and have tried:

isTrue = (int)dbReader["IsTrue"]

and

isTrue = Convert.ToBoolean((int)dbReader["IsTrue"])

Both give me a "Specified cast is not valid".

Is there a simple way to do this other then

isTrue = false
if ((int)dbReader["IsTrue"] == 1)
    isTrue = true;

Thanks,

Tom

isTrue = Convert.ToBoolean( dbReader["IsTrue"])
should do the trick, there is no need to cast it

WARNING, you have to make sure that the value is not null because it
will fail then
 
J

Jeroen Mostert

tshad said:
I have a value in my sql table set to tinyint (can't set to bit).

I am trying to move it into a boolean field in my program and have tried:

isTrue = (int)dbReader["IsTrue"]

and

isTrue = Convert.ToBoolean((int)dbReader["IsTrue"])

Both give me a "Specified cast is not valid".
The SQL TINYINT type is mapped to the .NET "Byte" type. While you can cast a
byte to an int, you can't cast a byte boxed as an object to int, as that
will not invoke any conversions.
Is there a simple way to do this other then

isTrue = false
if ((int)dbReader["IsTrue"] == 1)
isTrue = true;
This will not work either, for the same reason.

Ignacio already answered this one. Use Convert.ToBoolean directly and don't
involve any casts. If the value can be NULL, you have to check:

isTrue = !dbReader.IsDBNull(dbReader.GetOrdinal("IsTrue")) &&
Convert.ToBoolean(dbReader["IsTrue"]));

Or:

object o = dbReader["IsTrue"];
isTrue = o != DBNull.Value && Convert.ToBoolean(o);

If you feel confident, you can cast the column to byte, but then everything
will break if it's ever changed to smallint, int or bit (none of which are
unlikely).
 
T

tshad

message
How about:
isTrue = (dbReader("IsTrue") <> 0

Actually, it would be something like:

isTrue = (int)dbReader["IsTrue"] != 0;

or

isTrue = ((int)dbReader["IsTrue"]) != 0;

but I get the same error.

Thanks,

tom




Tom Dacon
Dacon Software Consulting
tshad said:
I have a value in my sql table set to tinyint (can't set to bit).
I am trying to move it into a boolean field in my program and have
tried:
isTrue = (int)dbReader["IsTrue"]
and
isTrue = Convert.ToBoolean((int)dbReader["IsTrue"])
Both give me a "Specified cast is not valid".
Is there a simple way to do this other then
isTrue = false
if ((int)dbReader["IsTrue"] == 1)
isTrue = true;
Thanks,
Tom- Hide quoted text -

- Show quoted text -
what error r u getting?

I figured it out, but the error was:

"Specified cast is not valid".

The problem was that I was using a tinyint and needed to use byte (short
didn't seem to work, either).

Thanks,

Tom
 
T

tshad

Jeroen Mostert said:
tshad said:
I have a value in my sql table set to tinyint (can't set to bit).

I am trying to move it into a boolean field in my program and have tried:

isTrue = (int)dbReader["IsTrue"]

and

isTrue = Convert.ToBoolean((int)dbReader["IsTrue"])

Both give me a "Specified cast is not valid".
The SQL TINYINT type is mapped to the .NET "Byte" type. While you can cast
a byte to an int, you can't cast a byte boxed as an object to int, as that
will not invoke any conversions.

That was what I found out, and did this to solve the problem:

IsTrue = (byte)dbReader["IsTrue"] == 1;

But I like Ignacios way better.

Thanks,

Tom
Is there a simple way to do this other then

isTrue = false
if ((int)dbReader["IsTrue"] == 1)
isTrue = true;
This will not work either, for the same reason.

Ignacio already answered this one. Use Convert.ToBoolean directly and
don't involve any casts. If the value can be NULL, you have to check:

isTrue = !dbReader.IsDBNull(dbReader.GetOrdinal("IsTrue")) &&
Convert.ToBoolean(dbReader["IsTrue"]));

Or:

object o = dbReader["IsTrue"];
isTrue = o != DBNull.Value && Convert.ToBoolean(o);

If you feel confident, you can cast the column to byte, but then
everything will break if it's ever changed to smallint, int or bit (none
of which are unlikely).
 
A

Arne Vajhøj

Jeroen said:
tshad said:
I have a value in my sql table set to tinyint (can't set to bit).

I am trying to move it into a boolean field in my program and have tried:

isTrue = (int)dbReader["IsTrue"]

and

isTrue = Convert.ToBoolean((int)dbReader["IsTrue"])

Both give me a "Specified cast is not valid".
The SQL TINYINT type is mapped to the .NET "Byte" type. While you can
cast a byte to an int, you can't cast a byte boxed as an object to int,
as that will not invoke any conversions.

The funny looking:

(int)(byte)dbReader["IsTrue"]

should work.
Ignacio already answered this one. Use Convert.ToBoolean directly and
don't involve any casts. If the value can be NULL, you have to check:

isTrue = !dbReader.IsDBNull(dbReader.GetOrdinal("IsTrue")) &&
Convert.ToBoolean(dbReader["IsTrue"]));

Or:

object o = dbReader["IsTrue"];
isTrue = o != DBNull.Value && Convert.ToBoolean(o);

If you feel confident, you can cast the column to byte, but then
everything will break if it's ever changed to smallint, int or bit (none
of which are unlikely).

I have the exact opposite opinion.

I like the cast.

Because if the field get changed from TINYINT to INT then I will like
to see a cast exception, because if the range 0-255 is too small,
then converting it to a boolean is most likely wrong !

Arne
 
P

Pavel Minaev

Because if the field get changed from TINYINT to INT then I will like
to see a cast exception, because if the range 0-255 is too small,
then converting it to a boolean is most likely wrong !

If an integer field is used to store boolean values, it hardly matters
whether the range is 0..2^8-1 or 0..2^32-1. I would agree if the
original field type was BOOLEAN or BIT (for those datbases which
support it).
 
T

Tom Dacon

Oops, I used VB syntax by mistake.

Tom

tshad said:
Tom Dacon said:
How about:

isTrue = (dbReader("IsTrue") <> 0

Actually, it would be something like:

isTrue = (int)dbReader["IsTrue"] != 0;

or

isTrue = ((int)dbReader["IsTrue"]) != 0;

but I get the same error.

Thanks,

tom
Tom Dacon
Dacon Software Consulting

tshad said:
I have a value in my sql table set to tinyint (can't set to bit).

I am trying to move it into a boolean field in my program and have
tried:

isTrue = (int)dbReader["IsTrue"]

and

isTrue = Convert.ToBoolean((int)dbReader["IsTrue"])

Both give me a "Specified cast is not valid".

Is there a simple way to do this other then

isTrue = false
if ((int)dbReader["IsTrue"] == 1)
isTrue = true;

Thanks,

Tom
 
A

Arne Vajhøj

Pavel said:
If an integer field is used to store boolean values, it hardly matters
whether the range is 0..2^8-1 or 0..2^32-1. I would agree if the
original field type was BOOLEAN or BIT (for those datbases which
support it).

If it is changed from TINYINT to INT it obviously means that
it is no longer storing boolean values.

And then getting an exception is much better than getting
the boolean test silently converted to a != 0 test.

Arne
 
J

Jeroen Mostert

Arne said:
If it is changed from TINYINT to INT it obviously means that
it is no longer storing boolean values.
Not at all. I would change a column from TINYINT to INT if I found out it
speeded up processing, for example, which could be for any number of reasons
(row alignment, preventing conversions when mixed with other data, the
phase of the moon).

If the column was properly typed it would be a BIT to begin with, so there's
not much to the claim that going from TINYINT to INT is semantically
significant any more than using TINYINT instead of BIT is.

In that vein, it would probably be a good idea to have a view or stored
procedure that *does* return the column as BIT if it's really only storing
booleans, because abstracting away from the physical storage is just what a
good database should be doing for you.
 
A

Arne Vajhøj

Jeroen said:
Not at all. I would change a column from TINYINT to INT if I found out
it speeded up processing, for example, which could be for any number of
reasons (row alignment, preventing conversions when mixed with other
data, the phase of the moon).

Row alignment in a database ?? That sounds about as good an explanation
as the moon !

But even if it do happen, then the fact that it could be because of
a fundamental change of type makes cast better than the Convert.

Arne
 
J

Jeroen Mostert

Arne said:
Row alignment in a database ?? That sounds about as good an explanation
as the moon !
I've never seen a real-world case where it was an issue, but it's far from
inconceivable. CPUs still access aligned data faster than unaligned data, so
aligning your data on disk may ultimately align your data in memory in such
a way that there's a benefit. On the other hand, of course, increasing your
row size increases the number of pages, which in turn can adversely affect
performance. So I'm not tuning my tables for alignment just yet...
But even if it do happen, then the fact that it could be because of
a fundamental change of type makes cast better than the Convert.
It doesn't matter what might be the case, it matters what the case is. Your
talking in absolutes makes me uncomfortable.

If the change is a "fundamental change of type", in that the field now
stores *more* than a boolean value, then the cast was a good idea because
the code will obviously fail. It should fail because otherwise we might
silently accept bad data, which could lead to corruption. Our code is good
because it did not rely on the database being correct. We now have outage,
but that's better than corruption.

If the change is not a "fundamental change of type", in that the field
*still* stores boolean values, just in a different size on disk, then the
cast was not a good idea because the code will obviously fail. It should not
fail because there is no bad data, no more than there was before. Our code
is bad because it did not rely on the database being correct. We now have
outage where we could have continued running.

If the program chooses to define "boolean stored in a table" as "any
integral type with values of 0 meaning False and values not 0 meaning True"
then it may behave unexpectedly if someone doesn't realize that that's how
things work. This is a viable solution, but it may not be optimal in all cases.

If the program chooses to define "boolean stored in a table" as "a TINYINT
with 0 meaning False and 1 meaning True and anything else being an error"
then the program will require maintenance if the underlying type of the
field is changed, which forces us to check if everything still works
correctly. This is a viable solution, but it may not be optimal in all cases.

Best of *all*, in my opinion, is if the program cannot have this problem in
the first place because it has hard guarantees that the data is delivered as
BIT. If this is made part of the database interface, it's no longer our
concern but the concern of the database hackers. Unless we are also the
database hackers, but you get my drift.
 
A

Arne Vajhøj

Jeroen said:
It doesn't matter what might be the case, it matters what the case is.

No. Code should be robust against general changes not only
cover specific changes.
Your talking in absolutes makes me uncomfortable.

I *am* absolutely for type safety.
If the change is a "fundamental change of type", in that the field now
stores *more* than a boolean value, then the cast was a good idea
because the code will obviously fail. It should fail because otherwise
we might silently accept bad data, which could lead to corruption. Our
code is good because it did not rely on the database being correct. We
now have outage, but that's better than corruption.

If the change is not a "fundamental change of type", in that the field
*still* stores boolean values, just in a different size on disk, then
the cast was not a good idea because the code will obviously fail. It
should not fail because there is no bad data, no more than there was
before. Our code is bad because it did not rely on the database being
correct. We now have outage where we could have continued running.

Your analysis is correct, but the conclusion is based on no unit
test and no system test.

If you happen to test then it is:

cast:
boolean - found in unit test and fixed => working
numeric - found in unit test and fixed => working

Convert:
boolean - working
numeric - found in system test and fixed => working
not found in system test => problem

cast is absolutely better than Convert.

Arne
 
J

Jeroen Mostert

Arne said:
No. Code should be robust against general changes not only
cover specific changes.
My point is this: if program A is *defined* to handle changes from TINYINT
to INT in a well-defined way (by not caring about the integral type), it's
no less robust than program B, which insists on handling TINYINT only.
They're just *different programs*. Whoever changes things should be aware of
that, because it determines how he can change things.
I *am* absolutely for type safety.
So am I, if we're talking about type-safe languages. But we're talking about
how a change in database type could affect a program. Whether the program
itself is type-safe in the usual sense makes no observable difference, what
matters is how it treats its input. So I don't think type safety can be used
as an easy indicator of right and wrong here.
Your analysis is correct, but the conclusion is based on no unit
test and no system test.
Yes, it is. I'm assuming that the database change is done without a full
retest of all applications using it. Even if a system test can be arranged,
unit tests may not be feasible if we have no complete list of which
applications use the database, or if we cannot allocate programmer time to
test them all. This is in no way an impossible or unlikely scenario, even if
it's not the scenario you'd want.

Also, you left out my second batch of remarks: if it's in the program's
*specification* that its idea of a valid boolean value is broader than a
TINYINT, there's nothing wrong with the change *or* the program.
If you happen to test then it is:

cast:
boolean - found in unit test and fixed => working
numeric - found in unit test and fixed => working

Convert:
boolean - working
numeric - found in system test and fixed => working
not found in system test => problem

cast is absolutely better than Convert.
I see your point and I agree with it, but by now we're talking about
different scenarios.
 
A

Arne Vajhøj

Jeroen said:
My point is this: if program A is *defined* to handle changes from
TINYINT to INT in a well-defined way (by not caring about the integral
type), it's no less robust than program B, which insists on handling
TINYINT only. They're just *different programs*. Whoever changes things
should be aware of that, because it determines how he can change things.

I don't agree.

All programs that follow their specification is not equally robust.

Robustness imply some ability to handle problems.

It is not good programming practice to assume all perfect
implementations.
So am I, if we're talking about type-safe languages. But we're talking
about how a change in database type could affect a program. Whether the
program itself is type-safe in the usual sense makes no observable
difference, what matters is how it treats its input. So I don't think
type safety can be used as an easy indicator of right and wrong here.

I think it can.

The use of cast require the code and the database to use same
type.

The use of convert makes some maybe good maybe bad conversions
between types.
Yes, it is. I'm assuming that the database change is done without a full
retest of all applications using it. Even if a system test can be
arranged, unit tests may not be feasible if we have no complete list of
which applications use the database, or if we cannot allocate programmer
time to test them all. This is in no way an impossible or unlikely
scenario, even if it's not the scenario you'd want.

Neither unit tests or systems test are perfect. But in case of the
cast issue it will fail 100% of times executed.

I don't think it is an unreasonable expectation that a line of code
is executed at least once before going in production.
I see your point and I agree with it, but by now we're talking about
different scenarios.

As far as I can see it is the scenario we are discussing.

Arne
 
J

Jeroen Mostert

Arne Vajhøj wrote:
It is not good programming practice to assume all perfect
implementations.
We're not breaking any new ground, and this has gone past the point of
diminishing returns. Either I'm not capable of explaining what I mean or
we're just having a fundamental difference in opinion, so I'll stop.
 

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