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

Nullable Support in ADO.NET

If you've been experimenting with generics lately, specifically the Nullable<T> generic, you may have noticed the following pitfall in their implementation.

You can't pass a Nullable<T> as the value parameter of a SqlParameter

Using Something like the following code...

public DataSet GetOrders(DateTime? StartOrderDate, DateTime? EndOrderDate)
{
 using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString))
 {
  DataSet ds = new DataSet();

  SqlCommand cmd = new SqlCommand("select * from orders " +
   "where (@StartOrderDate is null or OrderDate > @StartOrderDate) " +
   "and (@EndOrderDate is null or OrderDate < @EndOrderDate) ", conn);
  cmd.Parameters.AddWithValue("@StartOrderDate", StartOrderDate);
  cmd.Parameters.AddWithValue("@EndOrderDate", EndOrderDate);

  SqlDataAdapter da = new SqlDataAdapter(cmd);

  da.Fill(ds);
  return ds;
 }
}

will produce an ArgumentException with a message "No mapping exists from object type System.Nullable`1[[System.DateTime, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] to a known managed provider native type." will be thrown.  This certainly isn't the expected outcome. One would hope that it would just accept the value and continue along its merry way, however that just isn't the case.

While at TechEd 2005 last week, I talked to some of the ADO.NET team and they said that the functionality had been cut from the product for performance and time considerations.  Although I can see how performance could be an issue, due to testing for INullable on every parameter passed in, I think the user experience would be improved by allowing the Nullable<T> to be passed in.  Since the main reason it was excluded is due to performance considerations, maybe adding overloads to the cmd.Parameters.AddWithValue  method taking each individual nullable type as a parameter would fix things up, without producing a performance hit.  So you could still add parameters normally, however if you're using a Nullable<T> then and only then you would incur a minor performance hit, since with overloads you wouldn't need to use the “is“ operator.  Otherwise developers are either going to not realize there's an issue or develop the checking themselves, in which case they'd incur the performance hit anyway.  Here's the method i use in order to create parameters containing Nullable<T> values.  Note: By no means is this as performat as creating a overload for each Nullable<T> such as int?, DateTime?, etc, but it'll do for my small little app.

public System.Data.IDataParameter GetDataParameter(string Name, object Value)
{
 if (Value is INullableValue)
 {
  INullableValue nullableValue = (INullableValue)Value;
  if (nullableValue.HasValue)
  {
   return new SqlParameter(Name, nullableValue.Value);
  }
  else
  {
   return new SqlParameter(Name, DBNull.Value);
  }
 }
 else if (Value == null)
 {
  return new SqlParameter(Name, DBNull.Value);
 }
 return new SqlParameter(Name, Value);
}

If anybody has anything better than this, I'd be interested in hearing from you.

 

Published Saturday, June 11, 2005 1:01 PM by richc
Filed under: ,

Comments

 

richc said:

Oh man that sucks! Not your code, but the fact that Nullable types are not supported. Seems like the main reason to have nullable types. Ask Anders Hejlsberg. :-)

I am so underwhelmed right now. :-)
September 8, 2005 7:12 PM
Anonymous comments are disabled