Explain attributes of DataAnnotations which impacts the schema of database?

Posted by  Joseph Rossignol
 1732  View(s)
Ratings:
Rate this:

Explain to me about different attributes of DataAnnotations which impacts the schema of the database with example.

  1. Re: Explain attributes of DataAnnotations which impacts the schema of database?

    The System.ComponentModel.DataAnnotations.Schema namespace includes the following attributes which impact the schema of the database.

    Table

    The default Code First convention creates a table name same as the class name. If we are getting Code First create the database, we can also change the name of the tables it is creating. We can use Code First with an existing database but it's not always the case that the names of the classes match the names of the tables in our database.

    This table attribute overrides this default convention. The EF Code First will create a table with a specified name in Table attribute for a given domain class.

     [Table("StudentsInfo")]
    
    public class Student{
       [Key]
       public int StdntID { get; set; }

       [Required]
       public string LastName { get; set; }

       [Required]
       public string FirstMidName { get; set; }
       public DateTime EnrollmentDate { get; set; }

       public virtual ICollection<Enrollment> Enrollments { get; set; }
    }

    Column

    The column is also the same as Table attribute, but Table attribute overrides the table behavior while the Column attribute overrides the column behavior and by default Code First convention creates a column name same as the property name.

    If we are letting Code First create the database, and we also want to change the name of the columns in our tables. The Column attribute overrides this default convention. The EF Code First will create a column with a specified name in the Column attribute for a given property.

       public class Student{
    
       public int ID { get; set; }
       public string LastName { get; set; }

       [Column("FirstName")]
       public string FirstMidName { get; set; }
       public DateTime EnrollmentDate { get; set; }

       public virtual ICollection<Enrollment> Enrollments { get; set; }
    }

    Index

    This Index attribute was introduced in Entity Framework 6.1. We can create an index on one or more columns using the IndexAttribute and adding the attribute to one or more properties will cause EF to create the corresponding index in the database is created when it creates the database.

    These Indexes make the retrieval of data faster and efficient, in most cases but however, overloading a table or view with indexes could unpleasantly affect the performance of other operations such as inserts or updates.

    So, Indexing is the new feature in Entity Framework where we can improve the performance of our Code First application by reducing the time required to query data from the database.

    The default, indexes are non-unique, but we can use the IsUnique named parameter to specify that an index should be unique and the following example introduces a unique index

    public class Course{
    
       public int CourseID { get; set; }
       [Index(IsUnique = true)]

       public string Title { get; set; }
       [Index]

       public int Credits { get; set; }

       public virtual ICollection<Enrollment> Enrollments { get; set; }
    }

    ForeignKey

    The Code First convention will take care of the most common relationships in our model, but there are some cases where it needs help for example, by changing the name of the key property in the Student class created a problem with its relationship to Enrollment class.

    So while generating the database, Code First sees the StudentID property in the Enrollment class and recognizes it, by the convention that it matches a class name plus “ID”, as a foreign key to the Student class and there is no StudentID property in the Student class, rather it is StdntID property in Student class.

    Now the solution for this is to create a navigation property in the Enrollment and use the ForeignKey DataAnnotation to help Code First understand how to build the relationship between the two classes

    public class Enrollment{
    
       public int EnrollmentID { get; set; }
       public int CourseID { get; set; }
       public int StudentID { get; set; }
       public Grade? Grade { get; set; }
       public virtual Course Course { get; set; }

       [ForeignKey("StudentID")]
       public virtual Student Student { get; set; }
    }

    NotMapped

    The default conventions of Code First, every property that is of a supported data type and which includes getters and setters are represented in the database and this isn’t always the case in applications. The NotMapped attribute overrides this default convention, for example, we might have a property in the Student class such as FatherName, but it does not need to be stored. We can apply NotMapped attribute to a FatherName property, which we do not want to create a column in a database.

    We can see that the NotMapped attribute is applied to the FatherName property and when the table is generated, we will see that the FatherName column will not be created in a database, but it is present in the Student class.

    InverseProperty

    The InverseProperty is used when you have multiple relationships between classes. In the Enrollment class, you may want to keep track of who enrolled in a Current Course and who enrolled in a Previous Course.

    We will also need to add in the Course class referenced by these properties and the Course class has navigation properties back to the Enrollment class, which contains all the current and previous enrollments.

    public class Course{
    
       public int CourseID { get; set; }
       public string Title { get; set; }
       [Index]

       public int Credits { get; set; }
       public virtual ICollection<Enrollment> CurrEnrollments { get; set; }
       public virtual ICollection<Enrollment> PrevEnrollments { get; set; }
    }

    Now to fix these problems, we can use the InverseProperty annotation to specify the alignment of the properties.

    public class Course{
    
       public int CourseID { get; set; }
       public string Title { get; set; }

       [Index]
       public int Credits { get; set; }

       [InverseProperty("CurrCourse")]
       public virtual ICollection<Enrollment> CurrEnrollments { get; set; }

       [InverseProperty("PrevCourse")]
       public virtual ICollection<Enrollment> PrevEnrollments { get; set; }
    }

Answer