Passing DBNull as a function parameter

S

sean_walsh

I have a gridview with an imagebutton, and I pass the value of a field
to a function to retrieve which URL to use for the image. So in the
gridview I have this:

ImageUrl='<%# GetEnabledImage(Eval("Enabled")) %>'

In my codebehind, I want the function to handle three options: True,
False & Null. It would be ideal if I could declare the function as
something like this:

protected string GetEnabledImage(System.Data.SqlTypes.SqlBinary
Enabled)

....and then check the null status, or the value. That would be clean &
elegant. However, from what I understand, the DBNull type object gets
passed instead of the SqlBinary if the value is null in the DB, so the
wrong type is used, so it fails. Is there no way of doing this without
having a messy conditional statement in the gridview?
 
S

sean_walsh

Sorry. There IS a way, if I declare my function as:

protected string GetEnabledImage(object Enabled)
{
if (Enabled == DBNull.Value) { return ""; }
else if (Convert.ToBoolean(Enabled) == true) { return "/Admin/
App_Themes/images/Tick.png"; }
else { return "/Admin/App_Themes/images/Cross.png"; }
}

.... but that doesn't seem very elegant either - I don't like using
such a generic object type...

Why can't the SQL data types hold Null's within them, rather than
having a completely separate type?
 
H

Hans Kesting

sean_walsh formulated on maandag :
In my codebehind, I want the function to handle three options: True,
False & Null.

What about a Nullable<bool> as type? ("bool?" in C#). That accepts your
three options.

Hans Kesting
 
J

Jeff Johnson

In my codebehind, I want the function to handle three options: True,
False & Null. It would be ideal if I could declare the function as
something like this:

protected string GetEnabledImage(System.Data.SqlTypes.SqlBinary
Enabled)

SqlBinary is NOT for Boolean values. It is for storing bytes. Use SqlBoolean
if you want Booleans (bits, in SQL Server terms).

And for reference, the SqlTypes structures have a static field called Null,
so you can pass <type>.Null to any parameter expecting the given type.
 
S

sean_walsh

sean_walsh formulated on maandag :


What about a Nullable<bool> as type? ("bool?" in C#). That accepts your
three options.

Hans Kesting

doesn't work.

i set the parameter type in the method to bool?, and then:

if i try (bool?) before parameter in the grid, i get "specified cast
is not valid" error.

if i try Convert.ToBoolean before the parameter in the grid, i get
"object cannot be cast from dbnull to other types" error.

if i dont try converting somehow, it's a type mismatch...
 
S

sean_walsh

that shoudl have been SqlBit, not SqlBoolend, sorry.

So I set my method to:

protected string GetEnabledImage(System.Data.SqlTypes.SqlBoolean?
Enabled)

in my gridview:

ImageUrl='<%# GetEnabledImage(Eval("Enabled")) %>'

now I get the error: The best overloaded method match for
'Properties.GetEnabledImage(System.Data.SqlTypes.SqlBoolean?)' has
some invalid arguments
 
J

Jeff Johnson

So I set my method to:
protected string GetEnabledImage(System.Data.SqlTypes.SqlBoolean?
Enabled)

Do NOT use the nullable version of this. Just use

protected string GetEnabledImage(System.Data.SqlTypes.SqlBoolean Enabled)

Then you're going to have to put a little more code in the declarative
property (or just do it in code-behind, which would be my choice):

ImageUrl='<%# GetEnabledImage((Eval("Enabled") == null ? SqlBoolean.Null :
new SqlBoolean(Eval("Enabled")))) %>'

Honestly, I can't even tell you if the code above will work, but that's the
gist of what it needs to do. Like I said, I'd do it in code-behind.
 
S

sean_walsh

I'd be interested in knowing how you do it in the code behind...

I tried this:
ImageUrl='<%# GetEnabledImage(Eval("Enabled")
== null ? System.DBNull.Value : new System.Data.SqlTypes.SqlBoolean
(Eval("Enabled"))) %>'
and:
protected string GetEnabledImage(System.Data.SqlTypes.SqlBoolean
Enabled)

and got:

Error 30 The best overloaded method match for
'System.Data.SqlTypes.SqlBoolean.SqlBoolean(bool)' has some invalid
arguments
Error 31 Argument '1': cannot convert from 'object' to 'bool'
 
H

Hans Kesting

sean_walsh pretended :
I'd be interested in knowing how you do it in the code behind...

I tried this:
ImageUrl='<%# GetEnabledImage(Eval("Enabled")
== null ? System.DBNull.Value : new System.Data.SqlTypes.SqlBoolean
(Eval("Enabled"))) %>'
and:
protected string GetEnabledImage(System.Data.SqlTypes.SqlBoolean
Enabled)

and got:

Error 30 The best overloaded method match for
'System.Data.SqlTypes.SqlBoolean.SqlBoolean(bool)' has some invalid
arguments
Error 31 Argument '1': cannot convert from 'object' to 'bool'

What is the type of "Enabled"? Apparently you get it from a database,
what is the columntype there?
The "Eval" method returns an object, and the SqlBoolean contructor
expects a bool, that is the source of your compiler error.

Why do you want to use a SqlBoolean? A "bool?" would also allow
true/false/null as values. To handle the DbNull, you could use the "as"
operator instead of a straight cast:

Eval("Enabled") as bool?

This will return null if 'Eval("Enabled")' can't be cast to a bool.


Hans Kesting
 
S

sean_walsh

Personally, I would think that if you get a value from the database,
then you should be able to cast that value to the type of column
stored in the database. Then in your codebehind, you handle whatever
you want, using the type that matches your database column. That seems
like a close integration to me.

As a newbie, though, it seems that the type you get back from the Eval
function, is either a Boolean if the db field is populated, or a
DBNull object. So that is the source of the problem.

So then I change the codebehind parameter to a bool? type. But now I
have to add to my gridview calling code, to change the object type to
a bool type. But I have to first check if it's a DBNull type (value),
and if it is, pass a bool? type of value null, else I pass it the
value of the object converted to a boolean.

Don't you think that sounds ridiculous, given that all you're trying
to do is handle a SqlBoolean value all along? i.e. if you were able to
use a SqlBoolean? type, then you would simply convert the Eval object
to that type, and regardless of whether it was null or populated, it
would work, and the implementation would be quite elegant, instead of
all the conditional checks and type-casting that messes everything
up...

I'm just saying it should be easier...
 
J

Jeff Johnson

I'd be interested in knowing how you do it in the code behind...

Well, I'm not really a Web guy, so I can't give you a solid answer. I would
expect that your control (a gridview, right?) would have "hooks" where you
can fine-tune thing. Maybe it's in an event that the control raises for
every row. Or every column. I don't know.
I tried this:
ImageUrl='<%# GetEnabledImage(Eval("Enabled")
== null ? System.DBNull.Value : new System.Data.SqlTypes.SqlBoolean
(Eval("Enabled"))) %>'
and:
protected string GetEnabledImage(System.Data.SqlTypes.SqlBoolean
Enabled)
Error 30 The best overloaded method match for
'System.Data.SqlTypes.SqlBoolean.SqlBoolean(bool)' has some invalid
arguments
Error 31 Argument '1': cannot convert from 'object' to 'bool'

Well, that error is basically telling you everything you need to know, but
you say you're new so I guess you just don't know how to interpret these
errors. It's saying that SqlBoolean's constructor wants a bool but you've
given it an object. You can extrapolate to determine that Eval() must be
returning an object. So cast it:

ImageUrl='<%# GetEnabledImage(Eval("Enabled") == null ? System.DBNull.Value
: new System.Data.SqlTypes.SqlBoolean((bool)Eval("Enabled"))) %>'

Might work, might not.

Now let's take a step back for a moment and talk about something I glossed
over at first: design. WHY is your bit column nullable in the first place?
I've worked with a lot of data and I can't recall ever having a good reason
to make a bit nullable. Either something is or it isn't. If this is some
kind of user selection and you want to indicate "user explicitly set it /
user explicitly cleared it / user never made a choice" then you have a
three-way condition, not a Boolean, and I would make it a numeric column. It
would be waaaaay easier to work with, for example, 1 / 2 / 3 above than all
these nullable hoops.
 

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