Entity Framework's auto generated class's code gets re generated every time model is updated

asp.net-mvc c# entity-framework entity-framework-6 sql-server

Question

I am using ADO.Net Entity Data Model which connects to a SQL Server database to generate entity classes.

I am creating partial classes for the generated classes with this attribute:

[MetadataType(typeof(Employee))] 

to put DataAnnotations on the fields. So I remove all fields from generated class (.g.cs) and move them to the other partial class and put the data annotations in this class.

The problem is whenever I update the model from database (regardless of whether I first deleting existing tables from entity data model or just refresh the model, the generated classes code gets regenerated. And I again have to manually delete the field attributes from g.cs classes because they already exist in other partial class (in the class specified by the MetadataType attribute).

Is it possible that when I update the model the generated code does not get regenerated and if required I can manually regenerate the code for particular table/class?

    [MetadataType(typeof(Employee))]
    public partial class Employee
    {
        public string badge_no { get; set; }
        public string first_name { get; set; }
        public string last_name { get; set; }

        [Display(Name="Name")]
        public string FullName { get { return first_name + " " + last_name; } }

        [Display(Name = "Badge-Name")]
        public string NameAndBadge { get { return badge_no + " " + FullName; } }
    }

and here is the g.cs file (generated file)

    public partial class Employee
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public Employee()
        {
            this.EmpWrkDesignations = new HashSet<EmpWrkDesignation>();
        }

        public int id { get; set; }
        //public string badge_no { get; set; }
        //public string first_name { get; set; }
        //public string last_name { get; set; }
        public System.DateTime row_added_date { get; set; }
        public Nullable<System.DateTime> row_changed_date { get; set; }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<EmpWrkDesignation> EmpWrkDesignations { get; set; }
    }
1
0
9/17/2017 7:57:50 AM

Popular Answer

You are using the MetadataTypeAttribute wrong. You should create a seperate class for the annotations.

I do it with a private inner class for example:

[MetadataType(typeof(Table1MetaData))]
public partial class Table1
{
    private class Table1MetaData
    {
        [MaxLength(20)]
        public string Foo { get; set; }
    }
}

Important thing is, that the property name of the MetaData class is the same as the partial one. So above, is the same as:

public partial class Table1
{
    [MaxLength(20)]
    public string Foo { get; set; }
}

You should go for the first one.

Also, since the class is partial, instead of:

public string first_name { get; set; }
public string last_name { get; set; }

[Display(Name="Name")]
public string FullName { get { return first_name + " " + last_name; }

You can and should write only your property:

[Display(Name="Name")]
public string FullName { get { return first_name + " " + last_name; }

Conclusion:

  1. Use MetadataType only for adding DataAnnotation Attribtues to generated properties.
  2. Don't create a variable that is already generated in a partial class. If you want to give it an attribute, see 1.

That said, if you are not comfortable the way Entity Framework generates code, you can edit the T4 template. It is hidden behind the edmx file (Just expand it).


You didn't asked, but you will came across earlier or later:

A pitfall is, if you having custom attributes, and want to get them, you need to check the metadata too:

public static TAttribute GetAttributeOrUseMetadata<TAttribute>(this PropertyInfo element, bool inherit = false) where TAttribute : System.Attribute
{
    //Find normal attribute
    var attribute = element.GetCustomAttribute<TAttribute>(inherit);
    if (attribute != null)
    {
        return attribute;
    }

    //Find via MetadataTypeAttribute
    if (element.DeclaringType != null)
    {
        var metadataType = element.DeclaringType.GetCustomAttribute<MetadataTypeAttribute>(inherit);
        var metadataPropertyInfo = metadataType?.MetadataClassType.GetProperty(element.Name);
        return metadataPropertyInfo?.GetCustomAttribute<TAttribute>();
    }
    return null;
}

An MVC alternative for this would be a custom DataAnnotationsModelMetadataProvider.

3
9/17/2017 8:35:38 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow