Thursday, October 29, 2009

Linq-To-Sql IsDbGenerated=true

Do you ever make changes to your database schema that's being mapped via dbml files? As far as I know the easiest way to update the dbml to match, is to delete the related tables from it, and then pull them back in from server explorer.

What do you lose when this happens? Any custom names you have given a foreign key relationship, Auto Generated=true (column attribute[Column(IsDbGenerated=true]) on fields that should use their default value like AddedDt columns.

So I haven't come up with a Design/compile time solution, but here's a run time solution I've come up with:

public partial class LqDataContext : System.Data.Linq.DataContext
{
    
partial void OnCreated()
    {
        
Debug.Assert(Linq.GetColumnAttribute<blogMain>(item => item.addedDt).IsDbGenerated );
    }
}


So if your program tries to create an instance of the dataContext an assertion fails. You could easily put this as one of your unit tests so that you are sure to check it before release. This makes use of the Member class and this method for getting the column attributes from a linq table:

    /// <summary>
        /// Uses an extra parameter to help with design-time and compile-time literal
        /// doesn't as easily get out of sync with the db
        /// Usage example:
        /// var columnInfo = Linq.GetColumnAttribute(Member.Name<zApplication>(item=>item.lastUser));
        /// </summary>
        /// <typeparam name="TEntity">Should be your linq entity</typeparam>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public static ColumnAttribute GetColumnAttribute<TEntity>(string fieldName)
        {
            System.Reflection.
PropertyInfo prop = typeof(TEntity).GetProperty(fieldName);
            
var info = prop.GetCustomAttributes(typeof(ColumnAttribute), true);
            
if (info != null && info.Length == 1)
            {
                
return (ColumnAttribute)info[0];
            }
            
return null;
        }


        
/// <summary>
        /// Uses an extra parameter to help with design-time and compile-time literal
        /// doesn't as easily get out of sync with the db
        /// Usage example:
        /// var columnInfo = Linq.GetColumnAttribute<zApplication>(item=>item.lastuser);         /// </summary>
        public static ColumnAttribute GetColumnAttribute<TEntity>(Expression<Action<TEntity>> fieldNameExpression)
        {
            
var fieldName = Member.Name<TEntity>(fieldNameExpression);
            
return GetColumnAttribute<TEntity>(fieldName);
        }

        
/// <summary>
        /// Uses an extra parameter to help with design-time and compile-time literal
        /// doesn't as easily get out of sync with the db
        /// Usage example:
        /// var columnInfo = Linq.GetColumnAttribute<zApplication>(item=>item.lastuser);
         /// </summary>
        public static ColumnAttribute GetColumnAttribute<TEntity>(Expression<Func<TEntity,object>> fieldNameExpression)
        {
            
var fieldName = Member.Name<TEntity>(fieldNameExpression);
            
return GetColumnAttribute<TEntity>(fieldName);
        }

1 comment: