Dammit

I was so proud.

The PHP Gallery-like project I’m working on involves storing a property about an individual’s gender, but it’s only a metadatum, so it might not be provided.

Now that’s fine, as Microsoft SQL Server can handle tristate “bit” fields, with values of 1, 0 or NULL. As a result, I created a C# enum like so:

namespace Foo.Bar
{
   /// <summary> Enumerator to contain individuals' gender.
   /// </summary>
   /// <remarks>
   /// Where the database provides <c>NULL</c>,
   /// the gender will be set to
   /// <see cref="GenderEnum.GenderUnknown"/>, with a
   /// value of <c>-1</c>
   /// </remarks>
   public enum GenderEnum : int
   {
      /// <summary> Male </summary>
      Male = 0,
      /// <summary> Female </summary>
      Female = 1,
      /// <summary> Gender unknown </summary>
      GenderUnknown = -1   // Int32s can't be null.
   }
}

So far so good. But now I need to be able to push it into a database on update (which was out of scope in the previous phase). That’s fine, but how do I get it to know my -1 is actually a NULL?

Well, I did have the following, and I was particularly proud of that deeply ugly else clause, with three type-casts in one line:

using System.Data.SqlTypes;

public static SqlBoolean GetDbValueFromGender(GenderEnum g)
{
   if (g == GenderEnum.GenderUnknown)
      return SqlBoolean.Null;
   else
      return (SqlBoolean) Boolean.Parse(g.ToString());
}

Initially, I’d even had a fourth typecast in there:

      return (SqlBoolean) (bool) Int32.Parse(g.ToString());

But neither of these works (the latter won’t even compile), as you can’t smoosh an int into a bool. For anyone who cares, the Enum.ToString() call reveals the internal (int) value of the enumeration variable, but as a string, hence the subsequent Parse calls.

Rather disappointingly, what I end up with is much less ugly-yet-efficient:

using System.Data.SqlTypes;

/// <summary>
/// Provides a <see cref="System.Data.SqlTypes.SqlBoolean"/>
/// from a <see cref="GenderEnum"/> value.
/// </summary>
/// <remarks>
/// I'm quite proud that this once contained the ugliest line of
/// code I'd ever written, with three type-casts in one line:
/// <code> return (SqlBoolean) Boolean.Parse(g.ToString()); </code>
/// Unfortunately, however, <see cref="Boolean.Parse"/> won't
/// accept integers <c>1</c> and <c>0</c> to
/// return <c>true</c> and <c>false</c>.
/// </remarks>
/// <param name="g">
/// The <see cref="GenderEnum"/> to push into a database.
/// </param>
/// <returns>
/// The <see cref="System.Data.SqlTypes.SqlBoolean"/> for the
/// <see cref="GenderEnum"/>.
/// </returns>
public static SqlBoolean GetDbValueFromGender(GenderEnum g)
{
   if (g == GenderEnum.GenderUnknown)
      return SqlBoolean.Null;
   else if (g == GenderEnum.Female)
      return SqlBoolean.One;
   else
      return SqlBoolean.Zero;
}

So much less satisfying.

Advertisements

Ymatebwch

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s