Data Annotations for EF Generated Classes

Generating classes using entity framework is fairly problem free most of the time but you’ll soon find limitations once you need to add anything extra to these classes. EF generated classes are by default created as partial classes. This gives you the flexibility to create another ‘part’ to the class where you can write any additional code (methods, properties, etc.) that don’t get generated by entity framework. Most of the time this is sufficient however I recently came across a scenario where this pattern doesn’t work, and that is when you need to add data annotations for EF generated classes.

The current project I am working on has the EF generated classes separated within the solution into their own project. This enables the entities to be used across the solution from the data project through to the web front end (ASP.Net MVC). In order to make use of the MVC Razor helpers and the MVC validation I needed to add data annotations to one of my classes. Adding the properties into the partial class and then decorating them with the required attributes won’t work in the scenario though as you can’t define the same property twice within a class (once in my partial class and once in the EF generated partial class).

Some research lead to two possible solutions. Both of which are very similar and make use of an attribute called MetadataType.

The first solution is to create another class alongside your partial. This class will contain all the properties along with the data annotations. You will then add the MetadataType attribute to the partial class and pass the type of your newly created meta data class. For example:

    [MetadataType(typeof(CreditNoteRecordMetaData))]
    public partial class CreditNoteRecord
    {
    }
 
    public class CreditNoteRecordMetaData
    {
        [Required]
        [DisplayName("Invoice Rate")]
        public decimal InvoiceRate { get; set; }
        [Required]
        [DisplayName("Working Days")]
        public decimal WorkingDays { get; set; }
    }

The other solution, which is very similar, is based on creating an interface for the class and within the partial class you inherit from this interface but you still need to add the MetadataType attribute. Here’s an example:

    [MetadataType(typeof(ICreditNoteRecord))]
    public partial class CreditNoteRecord : ICreditNoteRecord
    {
    }

    public interface ICreditNoteRecord
    {
        [Required]
        [DisplayName("Invoice Rate")]
        decimal InvoiceRate { get; set; }
        [Required]
        [DisplayName("Working Days")]
        decimal WorkingDays { get; set; }
    }

Personally I think the second solution is a little easier to read as it gets rid of the public keyword and you could also use the extra class in the first solution elsewhere accidentally, whereas this is prevented when using an interface.

Comments

comments powered by Disqus