views:

1887

answers:

3

I need to put a max length on my test field on my Views using ASP.NET MVC with the Entity Framework and I can't find how to get the max length of a varchar field.

Is there an easy way to get that, or any other property of a database field

thanks

+2  A: 

Update

I realize that this answer doesn't directly apply to EF. At the time that I answered, there had been no answers for about 20 minutes and I thought knowing how I solved a similar problem with LINQToSQL might help. Given that the OP basically used the same technique albeit with EF properties instead, seems to indicate that I made the right choice. I'm leaving this answer here for context and for those who get here having the same problem but with LINQToSQL.

Original

I don't know about EF, but LINQToSQL entity properties are decorated with ColumnAttributes. You may be able to get the ColumnAttribute from the PropertyInfo for the property by looking at the CustomAttributesCollection. The value of this attribute would need to be parsed for length. I do that in my validator classes to make sure that I'm not going to get a SQL error by using a string that is too long for my column.

This is the method I use to extract the column length for string properties.

    public static int MaximumPropertyLength( Type type, string propertyName )
    {
        int maximumLength = -1;
        PropertyInfo info = type.GetProperty( propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance );
        if (info != null)
        {
            var attribute = info.GetCustomAttributes( typeof( ColumnAttribute ), false )
                                .Cast<ColumnAttribute>()
                                .FirstOrDefault();
            if (attribute != null)
            {
                maximumLength = ExtractLength( attribute.DbType );
            }
        }
        return maximumLength;
    }

    private static int ExtractLength( string dbType )
    {
        int max = int.MaxValue;
        if (dbType.Contains( "(" ))
        {
            string[] parts = dbType.Split( new char[] { '(', ')' }, StringSplitOptions.RemoveEmptyEntries );
            if (parts.Length > 1)
            {
                int.TryParse( parts[1], out max );
            }
        }
        return max;
    }
tvanfosson
Thanks for the try but this doesn't seem to work with Entity Framework.
moi_meme
Then you don't know... LINQ to SQL is NOT the same.
Jason Short
I agree it wasn't an exact answer, but apparently it was helpful, though, since he ended up using reflection albeit using properties available in EF to do basically the same thing. I already said I hadn't used EF but was trying to give a pointer to how it could be done based on what I had done with L2S. I'm not sure what's up with the snide comment since I was merely trying to be as helpful as possible.
tvanfosson
+1  A: 

For EntityFramework you would need to add your own custom attributes to the classes using a Code Generator or T4 Template.

Then what tvanfosson stated above would hold true. EF does not persist this information by default.

http://blogs.msdn.com/adonet/archive/2008/01/24/customizing-code-generation-in-the-ado-net-entity-designer.aspx

Explains more of what I am talking about with your code generator. It is pretty slick I have done exactly what you are mentioning before, problem is with proprietary code so I do not have an example for you.

jwendl
+9  A: 

Here is how i manage to do it (with an extension method on entities) :

public static int? GetMaxLength(this EntityObject entite, string nomPropriete)
    {
        int? result = null;
        using (XEntities contexte = XEntities.GetCurrentContext())
        {
            var q = from meta in contexte.MetadataWorkspace.GetItems(DataSpace.CSpace)
                               .Where(m => m.BuiltInTypeKind == BuiltInTypeKind.EntityType)
                    from p in (meta as EntityType).Properties
                       .Where(p => p.DeclaringType.Name == entite.GetType().Name
                           && p.Name == nomPropriete
                           && p.TypeUsage.EdmType.Name == "String")
                    select p;

            var queryResult = from meta in contexte.MetadataWorkspace.GetItems(DataSpace.CSpace)
                               .Where(m => m.BuiltInTypeKind == BuiltInTypeKind.EntityType)
                              from p in (meta as EntityType).Properties
                                 .Where(p => p.DeclaringType.Name == entite.GetType().Name
                                     && p.Name == nomPropriete
                                     && p.TypeUsage.EdmType.Name == "String")
                              select p.TypeUsage.Facets["MaxLength"].Value;
            if (queryResult.Count() > 0)
            {
                result = Convert.ToInt32(queryResult.First());
            }
        }
        return result;
    }
moi_meme
Hi moi_meme,I'm trying your solution, but I don't find the `GetCurrentContext()` method on my entity type. Do I need something ? Is `XEntities` the name you choose at design time for your entities ?Thanks in advance ;-)
Shimrod
@Shimrod My XEntities is my ObjectContext, and GetCurrentContext simply return or create an ObjectContext... So You can Simply use new ObjectContext instead...
moi_meme
Yes, that's what I've come to. Now the query works, but seems to not read the metadata :-( (i.e. the value for maxlength for a given field (where I know the value is populated in the edmx file) is null...)
Shimrod
@Shimrod: This worked for me with ,Net 3.5...
moi_meme