24

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

Zach Johnson
  • 23,678
  • 6
  • 69
  • 86
moi_meme
  • 9,180
  • 4
  • 44
  • 63
  • The answer http://stackoverflow.com/a/12964634/52277 to a similar question is a type-safe generic method GetMaxLength(x => x.CustomerName); – Michael Freidgeim Jun 29 '13 at 06:31

3 Answers3

37

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 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;
    }
Richard Ev
  • 52,939
  • 59
  • 191
  • 278
moi_meme
  • 9,180
  • 4
  • 44
  • 63
  • 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 Jul 15 '10 at 12:59
  • @Shimrod My XEntities is my ObjectContext, and GetCurrentContext simply return or create an ObjectContext... So You can Simply use new ObjectContext instead... – moi_meme Jul 15 '10 at 19:15
  • 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 Jul 16 '10 at 07:02
  • Wouldn't the `using` statement dispose of the context at the end, making it a bad idea to return any "current" context that might be used elsewhere from `GetCurrentContext`. And if so, wouldn't `using (var context = new XEntities()) { ... }` be better? – Carl G Oct 12 '12 at 14:49
  • 2
    Using EF 4.1 I've used the `DbContext` objects rather than an `ObjectContext`. This Question: http://stackoverflow.com/questions/12378186/entity-framework-5-maxlength with similar code to the above helped me create a utility method for a given `DbContext`. – Rich Shealer Dec 26 '12 at 18:29
4

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
  • 524,688
  • 99
  • 697
  • 795
  • Thanks for the try but this doesn't seem to work with Entity Framework. – moi_meme Apr 14 '09 at 19:53
  • Then you don't know... LINQ to SQL is NOT the same. – Jason Short Nov 02 '09 at 17:09
  • 5
    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 Nov 02 '09 at 17:23
1

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
  • 942
  • 7
  • 13