Sunday, February 24, 2008
« Zune Software Install Failure. Fix: Enab... | Main | Convert an array of type string to type ... »

When you use the LINQ to SQL design surface in Visual Studio, the generated code contains a Column Attribute which in turn contains a small piece of SQL text called the DbType. This property contains the column length for columns of type Char and VarChar. Using a bit of reflection, you can gain access to the value. Wrapping all of this within an ExpressionBuilder, you can easily set the MaxLength property of any TextBox declaratively in your web pages.

Here is the code for the Expression Builder:

using System;

using System.CodeDom;

using System.Data.Linq.Mapping;

using System.Linq;

using System.Reflection;

using System.Web.Compilation;

using System.Web.UI;

 

namespace BinaryOcean.Web.Utility

{

    [ExpressionPrefix("LinqLength")]

    public class LinqLengthExpressionBuilder : ExpressionBuilder

    {

        public override CodeExpression GetCodeExpression(BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context)

        {

            string typeName = BeforeLast(entry.Expression, ".");

            string propertyName = AfterLast(entry.Expression, ".");

 

            return new CodePrimitiveExpression(PropertyLength(typeName, propertyName));

        }

 

        private int PropertyLength(string typeName, string propertyName)

        {

            ColumnAttribute attribute =

                (ColumnAttribute)BuildManager

                .GetType(typeName, true)

                .GetProperty(propertyName)

                .GetCustomAttributes(typeof(ColumnAttribute), false)

                .Single(); // <-- look, I just had to use a tiny bit of LINQ in this code!

 

            return int.Parse(BetweenFirst(attribute.DbType, "char(", ")"));

        }

 

        private string BeforeLast(string value, string last)

        {

            return value.Substring(0, value.LastIndexOf(last));

        }

 

        private string AfterLast(string value, string last)

        {

            return value.Substring(value.LastIndexOf(last) + last.Length);

        }

 

        private string BetweenFirst(string value, string startText, string endText)

        {

            int start = value.IndexOf(startText, StringComparison.OrdinalIgnoreCase) + startText.Length;

            int end = value.IndexOf(endText, start,  StringComparison.OrdinalIgnoreCase);

 

            return value.Substring(start, end - start);

        }

    }

}

You must add the following bit of code to the system.web / compilation section of your web.config file. This loads the ExpressionBuilder which interprets your code.

 

<system.web>

  <compilation debug="true">

    <expressionBuilders>

      <add expressionPrefix="LinqLength" type="BinaryOcean.Web.Utility.LinqLengthExpressionBuilder"/>

    </expressionBuilders>

  </compilation>

</system.web>

 

The use of BuildManager.GetType() within the Expression Builder should allow you to reference dbml objects within you local AppCode folder or either local or external namespaces. Given that Name is a database column contained within the Employee table you can code this:

 

<asp:TextBox ID="TextBoxName" runat="server" MaxLength='<%$LinqLength:Employee.Name%>' />

 

If you are using Web Projects or if your data context is in a different namespace from your web application, you will have to prefix the above type with your namespace (and add dot ("."));

 

Enjoy!

kick it on DotNetKicks.com   Sunday, February 24, 2008 3:43:19 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  |  Related posts:
LINQ WhereIf Extension Method