Got more questions? Find advice on: SQL | XML | Regular Expressions | Windows
in Search
Welcome to AspAdvice Sign in | Join | Help

Rich Czyzewski's Blog

Coding One Day at a Time

Adding Functionality to a Typed DataSet using Partial Classes

In continuing with my experimentation with generics... I've noticed that there is no way to get the Typed DataSet code generator to generate a DataRow object, which contains Nullable Types.  There are a number of column properties that seem to elude that the Typed DataSet is capable of doing this type of functionality, however none produce the expected results.  I've spoke with the ADO.NET team during TechEd about this and they said that the feature was cut from the final product due to time concerns, so you may think that you're always stuck with:

public bool IsShippedDateNull() {
    return this.IsNull(this.tableOrders.ShippedDateColumn);
}

public void SetShippedDateNull() {
    this[this.tableOrders.ShippedDateColumn] = System.Convert.DBNull;
}

public System.DateTime ShippedDate {
    get {
        try {
            return ((System.DateTime)(this[this.tableOrders.ShippedDateColumn]));
        }
        catch (System.InvalidCastException e) {
            throw new System.Data.StrongTypingException("The value for column \'ShippedDate\' in table \'Orders\' is DBNull.", e);
        }
    }
    set {
        this[this.tableOrders.ShippedDateColumn] = value;
    }
}

Right?  Wrong! Although the Typed DataSet designer isn't capable of producing code that takes advantage of Nullable (except in the TableAdaptor), doesn't mean you can't do it yourself.  Now you're probably thinking that I must have lost my mind, clearly if you make changes to the Typed DataSet's code file it'll get overwritten the next time it's regenerated. Although that continues to be the case, you may have noticed that Typed DataSets are now partial classes, meaning that we can add and sometimes override most functionality that we want in a separate file without the Typed DataSet code generator destroying our changes.

In my case the Typed DataSet I'm working with has a class name of OrdersDataSet and a Typed Row class named OrdersRow.  In the code below I've added a single nullable column to the partial class, which is just a wrapper for an existing column.

public partial class OrdersDataSet : System.Data.DataSet
{
 public partial class OrdersRow : System.Data.DataRow
 {
  public Nullable MyShippedDate
  {
   get
   {
    object o = this[this.tableOrders.ShippedDateColumn];
    if (o is DateTime)
    {
     return (DateTime)o;
    }
    return new Nullable();
   }
   set
   {
    if (value.HasValue)
    {
     this[this.tableOrders.ShippedDateColumn] = (DateTime)value;
    }
    else
    {
     this[this.tableOrders.ShippedDateColumn] = DBNull.Value;
    }
   }
  }
 }
}

You may be asking what this actually does for you.  First off, here's what it doesn't do... you can't bind to it in the front end, since technically a column named MyShippedDate doesn't exist.  I'm sure we could get the functionality if we really needed it, but that's beyond the scope of this blog entry. Also notice that we're forced to have a different name since we can't conflict with column names from the other partial class generated by the Typed DataSet generator. Coding a column as a Nullable in this manner allows you to work with it better in code. Let's say that you wanted to display Order Date in a label on a page. In the old way you'd have to run the IsShippedDateNull() method to determine whether or not you're capable of calling the property without an exception.  By adding a Nullable implementation you can now just call ToString() on the MyShippedDateDate and receive no Exceptions.  If there is a date, then ToString() will be called on that, otherwise you get an empty string.

Old Way:

OrdersDataSet.OrdersRow or = (OrdersDataSet.OrdersRow)ds.Tables[0].Rows[0];
if (!or.IsShippedDateNull())
{
 lblShippedDate.Text = or.ShippedDate.ToString("MM/dd/yy hh:mm tt");
}

New Way

lblShippedDate.Text = ((OrdersDataSet.OrdersRow)ds.Tables[0].Rows[0]).MyShippedDate.ToString("MM/dd/yy hh:mm tt");

Although the new way is only three lines of code shorter, imagine that applied of twenty different columns. That could drastically affect the readability of code interacting with a Typed DataSet. What would be really nice is to have a Code Generator of some sort that would generate either the Partial Class definition or generate an entirely new Typed DataSet, which has the option of supporting Nullable Columns.

Published Sunday, June 19, 2005 9:54 AM by richc
Filed under: ,

Comments

 

<Rolog> said:

Earlier today I answered a question on a group where some guy was trying to use nullable types with...
February 9, 2006 1:49 PM
 

<Rolog> said:

Earlier today I answered a question on a group where some guy was trying to use nullable types with...
February 9, 2006 1:50 PM
 

<Rolog> said:

Earlier today I answered a question on a group where some guy was trying to use nullable types with a...
February 17, 2006 9:31 PM
Anonymous comments are disabled