Entity Framework:- Automated Data Annotation with Database First Approach

In entity framework, we can have model (poco classes). By using database first approach we can generate our model classes also called complex types for table and store procedures automatically to save our time on model creation.
You can refer this link to know how to add .edmx file and generate model classes, http://www.asp.net/mvc/overview/getting-started/database-first-development/creating-the-web-application
Now what if someone told you to apply data annotation to all model class properties? It will lengthy task with lots of code and time consuming right. But there is one more problem, once you done with updating all model, all your changes may get reverted as soon as you update your model form database.  Because all model will generated to follow template defined in .tt file of .edmx.
“I have come across such situation, where I need to perform some security scan for application, (We were using VERACODE), and its giving us error CWE-100: Technology-Specific Input Validation Problems, As we are not doing model validation i.e. not applying data annotation for all properties of model. We getting this error for string and date properties.  All I need do is add data annotation for all such properties on model classes. “

This can be achieved this buy below methods,

1. Modifying existing .tt file
Yes it is possible. I have done it by modifying existing .tt file and then your model classes will get generated as you need with data annotation. We can do this by adding below additional code in .tt file which will generate our models with data annotation.
This can be done by following steps.
[NOTE: - I have been using EF6.0]

STEP 1. We need to add function to find data type and to return data annotation, open your .tt file and add below code to it, may be at line 254
    //////// Write data annotations to properties.
    private void WriteDataAnnotationforProperty(EdmProperty property)
    {
        MetadataTools ef = new MetadataTools(this);
              var dataTypeAtt = GetDataTypeAttribute(property, ef);
              WriteLine(string.Empty);
              foreach (Facet facet in property.TypeUsage.Facets)
        {
              if (facet.Name == "MaxLength" && facet.Value != null && facet.IsUnbounded == false)
                     {
                     WriteLine(string.Empty);
                     #>
                     [StringLength(<#=facet.Value#>)]<#+
                     }
                     else if (facet.Name == "MaxLength")
                     {
                     WriteLine(string.Empty);
                     #>
                     [MaxLength(int.MaxValue)]<#+
                     }                         
              }            
              if (dataTypeAtt != String.Empty)
              {
                     WriteLine(string.Empty);
                     #><#=dataTypeAtt#><#+
              }
#>
<#+
       }

public string GetDataTypeAttribute(EdmProperty property, MetadataTools ef)
{
       var propLower = property.Name.ToLower();
       if (ef.ClrType(property.TypeUsage) == typeof(System.DateTime))
       {
              return "[DataType(DataType.DateTime)]";
       }
       if (propLower.Contains("phone"))
       {
              return "[DataType(DataType.PhoneNumber)]";
       }
       if (propLower.Contains("html"))
       {
              return "[DataType(DataType.Html)]";
       }
       if (propLower.Contains("email"))
       {
              return "[DataType(DataType.EmailAddress)]";
       }
       if (propLower.Contains("url"))
       {
              return "[DataType(DataType.Url)]";
       }
       return String.Empty;
}

STEP 2. Find and add use newly created function
Ø  Apply data annotations to table properties.
Search for foreach (var edmProperty in simpleProperties) and above <#=codeStringGenerator.Property(edmProperty)#> Add below code <#WritePrimitiveTypeProperty(edmProperty); #>


Ø  Apply data annotations to store procedure properties.

Search for foreach(var edmProperty in simpleProperties) and above <#=codeStringGenerator.Property(edmProperty)#> add  <#WritePrimitiveTypeProperty(edmProperty); #>

Now just save .tt file, it will take some time, and now according to your template it will update all your model classes.


In same way you can add [Serializable] attribute to all your classes. To add,
Ø  For table, search for <#=codeStringGenerator.EntityClassOpening(entity)#> and add [Serializable] before it.
Ø  For store procedures. Search for <#=Accessibility.ForType(complex)#> partial class <#=code.Escape(complex)#> and add [Serializable] before it.


Data annotation to model objects can also be done using following techniques,

2. Add new metadata classes also called buddy classes manually and define data annotation into your application.
    [MetadataType(typeof(LoginMetaData))]
    public partial class Login
    {
        public bool IsSingleSignOn { get; set; }
    }

    public class LoginMetaData
    {
        [Required(ErrorMessage = "Please enter your username")]
        [Display(Name = "Username")]
        public string UserName { get; set; }

        [Required(ErrorMessage = "Please enter your password")]
        [StringLength(50)]
        public string Password { get; set; }
    }

3. Automatically Add/Crete Entity Framework buddy classes in to application automatically by adding one more .tt file (T4 Metadata and Data Annotations Template)


Comments

  1. Great blog. An important image annotation
    technique which outlines the object in the image with a box, for object classification and localization models.

    ReplyDelete
  2. I am really very happy to visit your blog. Directly I am found which I truly need. please visit our website for more information
    Data visualization Service in USA

    ReplyDelete

Post a Comment