Hoiw to expose a property that can be null.

  • Thread starter Thread starter MP
  • Start date Start date
M

MP

Hello,
I am trying to write a class that will expose some properties. One of the
property is extracted from a SQL database and can be NULL or some integer
value.

Is there a elegant way of implementing this in C# ? I do not want to use
variant (or similar types) because I want to retain a strnong types
property. Will I have no choices but to add another property that would
set/get the NULL value?

Thank you!
 
MP,

First off I would say don't allow null values , for example
integers can be defaulted to 0 or 1... But, there are
always those rare cases and of course the famous DateTime
which can be null in the db but NOT in C# so you will need
to provide a low level routine that converts values in
and out. For example, DateTime null in the db can be
converted to DateTime.MinValue in C# and then back
to null at storage time. We have elimited all nulls from
our database except for datetime and foriegn keys.
We then have a DAL tool that does the conversion
for us.

JIM
 
I know what you want to do, and I've battled with it in
the past, but understand there is no perfect answer here.
Think about it; you want strong typing but you're
breaching the concept of type "int" by adding in the
concept of DBNull. A true type "int" can be many things
but it can't be DBNull.

Anyway I've used both of these approaches before:

- If you implement the property as type DataColumn you
can 'set' the property to DBNull at will. However you
must ensure that a 'set' is setting the column to an int
value and, even uglier, the user takes on the
responsibility of calling MyProperty.Value.AsInt() each
time they wish to access the property. In this approach
you gain DBNull but lose compiler enforced "int-ness".

- You could also implement the property internally as a
DataColumn field but expose the property to the world as
an int; you the implementor handle type casting. The user
would see, aka 'get' and 'set' an int property. Under
this scheme you could initialize the property to DBNull at
startup. If the user never sets the property the internal
value of the property will be DBNull. If the user sets
the property it takes on the integer value. If the
user 'gets' the property they get an integer. If the
property is DBNull during a 'get' then you can throw a
DBNull exception or return 0 {or whatever}. The only
problem with this scheme is that once the property is set
to a non-null value then the user cannot reset it to
DBNull without a helper 'reset' method or a special
integer value that signals the property implementer to set
the value to DBNull...

--Richard
 
Thank you Jim,
I fully agree that mapping DbNULL to the real world does not make sense.
In some previous projects I moved away from DbNULLs for the very same
reason.... But on this one NULL's will stay ! <--- There is a joke in
there somewhere.


Thank you again.
 
Thank you Richard!

I appreciate your input.

Richard said:
I know what you want to do, and I've battled with it in
the past, but understand there is no perfect answer here.
Think about it; you want strong typing but you're
breaching the concept of type "int" by adding in the
concept of DBNull. A true type "int" can be many things
but it can't be DBNull.

Anyway I've used both of these approaches before:

- If you implement the property as type DataColumn you
can 'set' the property to DBNull at will. However you
must ensure that a 'set' is setting the column to an int
value and, even uglier, the user takes on the
responsibility of calling MyProperty.Value.AsInt() each
time they wish to access the property. In this approach
you gain DBNull but lose compiler enforced "int-ness".

- You could also implement the property internally as a
DataColumn field but expose the property to the world as
an int; you the implementor handle type casting. The user
would see, aka 'get' and 'set' an int property. Under
this scheme you could initialize the property to DBNull at
startup. If the user never sets the property the internal
value of the property will be DBNull. If the user sets
the property it takes on the integer value. If the
user 'gets' the property they get an integer. If the
property is DBNull during a 'get' then you can throw a
DBNull exception or return 0 {or whatever}. The only
problem with this scheme is that once the property is set
to a non-null value then the user cannot reset it to
DBNull without a helper 'reset' method or a special
integer value that signals the property implementer to set
the value to DBNull...

--Richard
 
MP said:
Hello,
I am trying to write a class that will expose some properties. One of the
property is extracted from a SQL database and can be NULL or some integer
value.

Is there a elegant way of implementing this in C# ? I do not want to use
variant (or similar types) because I want to retain a strnong types
property. Will I have no choices but to add another property that would
set/get the NULL value?

Thank you!

Look at the SqlInt32 data type (or other types in the
System.Data.SqlTypes namespace)
 
I would suggest to use System.Data.SqlTypes in the Data
Layer, I mean where you are moving data from the Db (with
a DataAdapter or with a DataCommand) to the memory
(DataSet, variables, Array, etc.) and vice versa.
That's because SqlTypes better represent the native Db
types (i.e. SqlDateTime have MinValue and MaxValue
different from System.DateTime; SqlDecimal can set Scale
and Precision while System.Decimal cannot, etc).

I would suggest to use NullableTypes in the Business Layer
and in the User Interface Layer because
- they are identical to the native .NET types
(NullableDateTime have MinValue and MaxValue
equals to System.DateTime MinValue and MaxValue,
etc.)
- they work with .NET Remoting
- they work with .NET Web Services
- they are data base agnostic
- they have the NullConvertClass that can be
used to seamlessly integrate NullableTypes
with Web server controls and WinForms controls
- they have the DbNullCOnvert class that converts
NullableTypes values to in-memory Db values
(Command Parameters, DataReader values, DataSet
column values) and vice versa

ciao, (luKa)
 
Back
Top