Posted By: phreaks | Aug 21st @ 10:07 AM
page 1 of 1
Comments: 15 | Views: 784
phreaks
phreaks
Messiah of Marxism
Does anyone have a work-around for the nullable type issue in a typed DataSet?

Typed DataSets are unable to have int, float, double etc columns that contain nulls.

Has this been addressed in 3.5 SP1 of the framework, if not WHY?

PerfectPhase
PerfectPhase
"This is not war, this is pest control!" - Dalek to Cyberman

Since when?  Name is a string, Size is a nullable int

var table = new DataSet1.NullTestDataTable();
var row = table.NewNullTestRow();
row.Name = "Stephen";
row.SetSizeNull();
table.AddNullTestRow(row);
var adpt = new DataSet1TableAdapters.NullTestTableAdapter();
adpt.Update(table);
var results = adpt.GetData();

jh71283
jh71283
Throw new System.Beverage. OutOfCoffeeException​()
switching off the enforceconstraints is a bit of a sledgehammer to crack a nut...

constraints within the datasets can be quite useful at times.
PerfectPhase
PerfectPhase
"This is not war, this is pest control!" - Dalek to Cyberman

You mean something other than setting AllowDBNull=true on the dataTable column? 
jh71283
jh71283
Throw new System.Beverage. OutOfCoffeeException​()
The other problem with nulls is when you try to read a null when using it as strongly typed.

e.g if Name is null, and you do a

dim A as string = datarow.name.tostring - it throws an exception - I can see why, but why can't we specify on the dataset that a Null returns string.empty?

You have to null check everythng before you use it, which can be a pain...
Roobin
Roobin
My 1303S
I just found this out the other day:

if Name is DBNull.Value then
string A = DataRow.Name.ToString();
would indeed throw an exception.

But give this a try:
string A = DataRow.Name as string;
This sets A to null if the casting fails! Perfect if you ask me!

Same goes for:
int? ID = DataRow.ID as int;
To make proper use of nullable ints Smiley

BTW I couldn't find the VB.NET equivalent Sad  I guess this is a perk when using C#. (correct me if I'm wrong!)

VB.NET uses TryCast:
Dim A as string = TryCast(DataRow.Name, string)
jh71283
jh71283
Throw new System.Beverage. OutOfCoffeeException​()
Interesting, I'll keep it in mind - thanks!

PerfectPhase
PerfectPhase
"This is not war, this is pest control!" - Dalek to Cyberman

In the dataset designer there is a option on the column for NullValue (set via the xsd as msprop:nullValue) that lets you configure the column behavior when null, throw an exception, return a null or string.empty for strings. 

As this is a codegen behavior, it's not something you can set directly on an untyped datacolumn.  It also only works for string types, not value types in the designer.  You can get in the xsd and do something like this for a int column:

<xs:element name="Size" type="xs:int" msprop:nullValue="-1"   .../>

Of course the typed datarow is a partial class so you can always do something like this

[code]
    public partial class DataSet1
    {
        public partial class NullTestRow : global::System.Data.DataRow
        {
            public int? SizeNullable
            {
                get
                {
                    if (this.IsSizeNull())
                    {
                        return null;
                    }
                    else
                    {
                        return ((int)(this[this.tableNullTest.SizeColumn]));
                    }
                }
            }
        }
    }
[/code]


Wonder if you could write a postSharp aspect that would add all these in for you at compile time?

P.S. Anyone know where the list of tags you can use on here is, quote, video etc...
Dr Herbie
Dr Herbie
Half the population have below average IQ
Roobin,
    For a start, you can't use the 'as' keyword for value types (like int or DateTime ro decimal ...), but if you'd still get an exception for a typed dataset if the value is DBNull (throws a StrongTypingException).

I usually go with the longwinded:
int? x = DataRow.IsMY_FIELDNull() ? null : DataRow.MY_FIELD;


Perhaps there's something you could do with lambda expressions to take the sting out?

Herbie
jh71283
jh71283
Throw new System.Beverage. OutOfCoffeeException​()
Yes I remember this now, but strings are the only ones it works on.

For instance I would like to return False if a bool is null, but I don't have that option without overriding it myself.

Same with int, if null, I may want a zero in that instance.

I'm not saying these should be the defaults, but it would be nice to have the option.

Maybe even the option to return the DefaultValue if null?
 
PerfectPhase
PerfectPhase
"This is not war, this is pest control!" - Dalek to Cyberman

Support for int? would be wonderfull, but in the mean time you can do the int returns zero on null if you change the setting via the xsd rather than the designer, and the designer will respect your change.  Same for the booleans

Not perfect but it gets you part way there.
Roobin
Roobin
My 1303S

Dr Herbie,

You are absolutely right. My mistake... Typo....

It should be:

int? ID = DataRow.ID as int?;


Works like a charm!

Dr Herbie
Dr Herbie
Half the population have below average IQ
But if, DataRow.ID is set to null in a typed dataset, don't you get the StringTypingException?  Wouldn't you have to call DataRow.IsIDNull() anyway?

I shall experiment later this evening.

Herbie
Roobin
Roobin
My 1303S
Dr Herbie is right! This thing only works for string values and then only when you set NullValue in the dataset designer to (Null) instead of (Throw exception).

For all other columns this is the rule: For columns not defined as System.String, the only valid value is (Throw exception).
This can work: string A = DataRow.Name as string;
This doesn't: int? ID = DataRow.ID as int?;
Sorry guys!