Debugging LINQ Problems

One of the bigger challenges comes from errors that occur due to inserts, updates, or deletes to the database.  This can be not so much from the LINQ side as an issue, but from the database side.  For instance, with LINQ to SQL, a LINQ object has a string as a property.  This property maps to a database column defined as nvarchar(50).  However, LINQ to SQL designer does not embed any length checking into the business object, so you can easily assign the property a string 60 characters long, which will blow up when it's passed to the SQL database.  The resulting error won't give you much information, such as the table/column this occurred for.  And if you have a lot of updates, this will be hard to figure out what went wrong.

The approach I've used to counteract this is to use reflection to access the ColumnAttribute class in the System.Data.Linq.Mapping namespace.  This attribute defines the database column name, data type, precision, scale, etc. that a column can be.  Using this information and with some added logic to take this information and translate it into validation rules, I could easily add more detailed error information that pinpointed the problem immediately.

The solution is to loop through the object's properties:

Type linqType = linqObject.GetType();
PropertyInfo[] linqProperties = linqType.GetProperties(); // all are public properties

foreach (PropertyInfo property in linqProperties)
{
    //Logic here
}

The ColumnAttribute can be retrieved through the use of property.GetCustomAttributes(typeof(ColumnAttribute), true).  This method returns an array of attributes, as some attributes can be used multiple times.  But ColumnAttribute is defined once, so accessing the zero index is good.  However, do it this way:

object[] attributes = property.GetCustomAttributes(typeof(ColumnAttribute), true);
if (attributes.Length > 0)
{
   //Process column
}

The DbType property contains a string like "DateTime", "DateTime Not Null", "NVarChar(50)", "int not null", etc.  Using this, the precision, scale, and data type can be parsed, using some extra logic to determine what precision and scale are, to make sure text isn't passed a specific length and numbers are within the correct range.  In addition, the not null text is placed in DbType, but there is a CanBeNull property that determines nullability.

The common problems are not null dates that haven't been assigned are values like "1/1/0001", and SQL's datetime requires a minimum of 1/1/1753.  Another issue is strings going beyond the length.  Numeric values with a precise precision and scale (like numeric(4,2)) translates to a decimal, so it's possible that value will be out of range.

Published Sunday, March 16, 2008 6:30 PM by bmains
Filed under:

Comments

No Comments