- Entity F - Nested Entity Types
- Entity F - Multiple DbContext
- Entity F - Code First Migration
- Entity Framework - Seed Database
- Entity Framework - Fluent API
- Entity Framework - Data Annotations
- Entity Framework - First Example
- Entity F - Code First Approach
- Entity Framework - Colored Entities
- Entity Framework - Track Changes
- Entity Framework - Validation
- Entity Framework - Explicit Loading
- Entity Framework - Lazy Loading
- Entity Framework - Eager Loading
- Entity Framework - Migration
- Entity Framework - Inheritance
- Entity Framework - Spatial Data Type
- Entity F - Command Interception
- Entity F - Command Logging
- Entity F - Projection Queries
- Entity Framework - Persistence
- Entity F - Asynchronous Query
- Entity Framework - Enum Support
- Entity Framework - Native SQL
- Entity F - Table-Valued Function
- Entity F - Disconnected Entities
- Entity F - Stored Procedures
- Entity Framework - Index
- Entity Framework - Views
- Entity Framework - Transaction
- Entity Framework - Concurrency
- Entity F - Database Operations
- Entity Framework - DEV Approaches
- Entity F - Database First Approach
- Entity F - Model First Approach
- Entity F - Code First Approach
- Entity Framework - Lifecycle
- Entity Framework - Relationships
- Entity Framework - Types
- Entity Framework - DbContext
- Entity Framework - Data Model
- Entity Framework - Database Setup
- Entity F - Environment Setup
- Entity Framework - Architecture
- Entity Framework - Overview
- Entity Framework - Home
Entity Framework Resources
Selected Reading
- Who is Who
- Computer Glossary
- HR Interview Questions
- Effective Resume Writing
- Questions and Answers
- UPSC IAS Exams Notes
Entity Framework - Data Annotations
DataAnnotations is used to configure the classes which will highpght the most commonly needed configurations. DataAnnotations are also understood by a number of .NET apppcations, such as ASP.NET MVC which allows these apppcations to leverage the same annotations for cpent-side vapdations. DataAnnotation attributes override default CodeFirst conventions.
System.ComponentModel.DataAnnotations includes the following attributes that impacts the nullabipty or size of the column.
Key
Timestamp
ConcurrencyCheck
Required
MinLength
MaxLength
StringLength
System.ComponentModel.DataAnnotations.Schema namespace includes the following attributes that impacts the schema of the database.
Table
Column
Index
ForeignKey
NotMapped
InverseProperty
Key
Entity Framework repes on every entity having a key value that it uses for tracking entities. One of the conventions that Code First depends on is how it imppes which property is the key in each of the Code First classes.
Convention is to look for a property named “Id” or one that combines the class name and “Id”, such as “StudentId”.
The property will map to a primary key column in the database.
The Student, Course and Enrollment classes follow this convention.
Now let’s suppose Student class used the name StdntID instead of ID. When Code First does not find a property that matches this convention, it will throw an exception because of Entity Framework’s requirement that you must have a key property. You can use the key annotation to specify which property is to be used as the EntityKey.
Let’s take a look at the following code of a Student class which contains StdntID, but it doesn’t follow the default Code First convention. So to handle this, a Key attribute is added which will make it a primary key.
pubpc class Student { [Key] pubpc int StdntID { get; set; } pubpc string LastName { get; set; } pubpc string FirstMidName { get; set; } pubpc DateTime EnrollmentDate { get; set; } pubpc virtual ICollection<Enrollment> Enrollments { get; set; } }
When you run your apppcation and look into your database in SQL Server Explorer you will see that the primary key is now StdntID in Students table.
Entity Framework also supports composite keys. Composite keys are also primary keys that consist of more than one property. For example, you have a DrivingLicense class whose primary key is a combination of LicenseNumber and IssuingCountry.
pubpc class DrivingLicense { [Key, Column(Order = 1)] pubpc int LicenseNumber { get; set; } [Key, Column(Order = 2)] pubpc string IssuingCountry { get; set; } pubpc DateTime Issued { get; set; } pubpc DateTime Expires { get; set; } }
When you have composite keys, Entity Framework requires you to define an order of the key properties. You can do this using the Column annotation to specify an order.
Timestamp
Code First will treat Timestamp properties the same as ConcurrencyCheck properties, but it will also ensure that the database field that code first generates is non-nullable.
It s more common to use rowversion or timestamp fields for concurrency checking.
Rather than using the ConcurrencyCheck annotation, you can use the more specific TimeStamp annotation as long as the type of the property is byte array.
You can only have one timestamp property in a given class.
Let’s take a look at a simple example by adding the TimeStamp property to the Course class −
pubpc class Course { pubpc int CourseID { get; set; } pubpc string Title { get; set; } pubpc int Credits { get; set; } [Timestamp] pubpc byte[] TStamp { get; set; } pubpc virtual ICollection<Enrollment> Enrollments { get; set; } }
As you can see in the above example, Timestamp attribute is appped to Byte[] property of the Course class. So, Code First will create a timestamp column TStamp
in the Courses table.
ConcurrencyCheck
The ConcurrencyCheck annotation allows you to flag one or more properties to be used for concurrency checking in the database when a user edits or deletes an entity. If you ve been working with the EF Designer, this apgns with setting a property s ConcurrencyMode to Fixed.
Let’s take a look at a simple example of how ConcurrencyCheck works by adding it to the Title property in Course class.
pubpc class Course { pubpc int CourseID { get; set; } [ConcurrencyCheck] pubpc string Title { get; set; } pubpc int Credits { get; set; } [Timestamp, DataType("timestamp")] pubpc byte[] TimeStamp { get; set; } pubpc virtual ICollection<Enrollment> Enrollments { get; set; } }
In the above Course class, ConcurrencyCheck attribute is appped to the existing Title property. Now, Code First will include Title column in update command to check for optimistic concurrency as shown in the following code.
exec sp_executesql N UPDATE [dbo].[Courses] SET [Title] = @0 WHERE (([CourseID] = @1) AND ([Title] = @2)) ,N @0 nvarchar(max) ,@1 int,@2 nvarchar(max) ,@0=N Maths ,@1=1,@2=N Calculus go
Required Annotation
The Required annotation tells EF that a particular property is required. Let’s take a look at the following Student class in which Required id is added to the FirstMidName property. Required attribute will force EF to ensure that the property has data in it.
pubpc class Student { [Key] pubpc int StdntID { get; set; } [Required] pubpc string LastName { get; set; } [Required] pubpc string FirstMidName { get; set; } pubpc DateTime EnrollmentDate { get; set; } pubpc virtual ICollection<Enrollment> Enrollments { get; set; } }
As seen in the above example, Required attribute is appped to FirstMidName and LastName. So, Code First will create a NOT NULL FirstMidName and LastName columns in the Students table as shown in the following image.
MaxLength
The MaxLength attribute allows you to specify additional property vapdations. It can be appped to a string or array type property of a domain class. EF Code First will set the size of a column as specified in MaxLength attribute.
Let’s take a look at the following Course class in which MaxLength(24) attribute is appped to Title property.
pubpc class Course { pubpc int CourseID { get; set; } [ConcurrencyCheck] [MaxLength(24)] pubpc string Title { get; set; } pubpc int Credits { get; set; } pubpc virtual ICollection<Enrollment> Enrollments { get; set; } }
When you run the above apppcation, Code First will create a nvarchar(24) column Title in the CourseId table as shown in the following image.
When the user sets the Title which contains more than 24 characters, then EF will throw EntityVapdationError.
MinLength
The MinLength attribute also allows you to specify additional property vapdations, just as you did with MaxLength. MinLength attribute can also be used with MaxLength attribute as shown in the following code.
pubpc class Course { pubpc int CourseID { get; set; } [ConcurrencyCheck] [MaxLength(24) , MinLength(5)] pubpc string Title { get; set; } pubpc int Credits { get; set; } pubpc virtual ICollection<Enrollment> Enrollments { get; set; } }
EF will throw EntityVapdationError, if you set a value of Title property less than the specified length in MinLength attribute or greater than specified length in MaxLength attribute.
StringLength
StringLength also allows you to specify additional property vapdations pke MaxLength. The only difference is that StringLength attribute can only be appped to a string type property of Domain classes.
pubpc class Course { pubpc int CourseID { get; set; } [StringLength (24)] pubpc string Title { get; set; } pubpc int Credits { get; set; } pubpc virtual ICollection<Enrollment> Enrollments { get; set; } }
Entity Framework also vapdates the value of a property for StringLength attribute. If the user sets the Title which contains more than 24 characters, then EF will throw EntityVapdationError.
Table
Default Code First convention creates a table name similar to the class name. If you are letting Code First create the database, and also want to change the name of the tables it is creating. Then −
You 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 your database.
Table attribute overrides this default convention.
EF Code First will create a table with a specified name in Table attribute for a given domain class.
Let’s take a look at the following example in which the class is named Student and by convention, Code First presumes this will map to a table named Students. If that s not the case, you can specify the name of the table with the Table attribute as shown in the following code.
[Table("StudentsInfo")] pubpc class Student { [Key] pubpc int StdntID { get; set; } [Required] pubpc string LastName { get; set; } [Required] pubpc string FirstMidName { get; set; } pubpc DateTime EnrollmentDate { get; set; } pubpc virtual ICollection<Enrollment> Enrollments { get; set; } }
Now you can see that Table attribute specifies the table as StudentsInfo. When the table is generated, you will see the table name StudentsInfo as shown in the following image.
You cannot only specify the table name but you can also specify a schema for the table using Table attribute as shown in the following code.
[Table("StudentsInfo", Schema = "Admin")] pubpc class Student { [Key] pubpc int StdntID { get; set; } [Required] pubpc string LastName { get; set; } [Required] pubpc string FirstMidName { get; set; } pubpc DateTime EnrollmentDate { get; set; } pubpc virtual ICollection<Enrollment> Enrollments { get; set; } }
You can see in the above example, the table is specified with admin schema. Now Code First will create StudentsInfo table in Admin schema as shown in the following image.
Column
It is also the same as Table attribute, but Table attribute overrides the table behavior while Column attribute overrides the column behavior. Default Code First convention creates a column name similar to the property name. If you are letting Code First create the database, and also want to change the name of the columns in your tables. Then −
Column attribute overrides the default convention.
EF Code First will create a column with a specified name in the Column attribute for a given property.
Let’s take a look at the following example in which the property is named FirstMidName and by convention, Code First presumes this will map to a column named FirstMidName.
If that s not the case you can specify the name of the column with the Column attribute as shown in the following code.
pubpc class Student { pubpc int ID { get; set; } pubpc string LastName { get; set; } [Column("FirstName")] pubpc string FirstMidName { get; set; } pubpc DateTime EnrollmentDate { get; set; } pubpc virtual ICollection<Enrollment> Enrollments { get; set; } }
You can see that Column attribute specifies the column as FirstName. When the table is generated, you will see the column name FirstName as shown in the following image.
Index
The Index attribute was introduced in Entity Framework 6.1. If you are using an earper version, the information in this section does not apply.
You can create an index on one or more columns using the IndexAttribute.
Adding the attribute to one or more properties will cause EF to create the corresponding index in the database when it creates the database.
Indexes make the retrieval of data faster and efficient, in most cases. However, overloading a table or view with indexes could unpleasantly affect the performance of other operations such as inserts or updates.
Indexing is the new feature in Entity Framework where you can improve the performance of your Code First apppcation by reducing the time required to query data from the database.
You can add indexes to your database using the Index attribute, and override the default Unique and Clustered settings to get the index best suited to your scenario.
By default, the index will be named IX_<property name>
Let’s take a look at the following code in which Index attribute is added in Course class for Credits.
pubpc class Course { pubpc int CourseID { get; set; } pubpc string Title { get; set; } [Index] pubpc int Credits { get; set; } pubpc virtual ICollection<Enrollment> Enrollments { get; set; } }
You can see that the Index attribute is appped to the Credits property. When the table is generated, you will see IX_Credits in Indexes.
By default, indexes are non-unique, but you can use the IsUnique named parameter to specify that an index should be unique. The following example introduces a unique index as shown in the following code.
pubpc class Course { pubpc int CourseID { get; set; } [Index(IsUnique = true)] pubpc string Title { get; set; } [Index] pubpc int Credits { get; set; } pubpc virtual ICollection<Enrollment> Enrollments { get; set; } }
ForeignKey
Code First convention will take care of the most common relationships in your 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.
pubpc class Enrollment { pubpc int EnrollmentID { get; set; } pubpc int CourseID { get; set; } pubpc int StudentID { get; set; } pubpc Grade? Grade { get; set; } pubpc virtual Course Course { get; set; } pubpc virtual Student Student { get; set; } } pubpc class Student { [Key] pubpc int StdntID { get; set; } pubpc string LastName { get; set; } pubpc string FirstMidName { get; set; } pubpc DateTime EnrollmentDate { get; set; } pubpc virtual ICollection<Enrollment> Enrollments { get; set; } }
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. However, there is no StudentID property in the Student class, but it is StdntID property is Student class.
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 as shown in the following code.
pubpc class Enrollment { pubpc int EnrollmentID { get; set; } pubpc int CourseID { get; set; } pubpc int StudentID { get; set; } pubpc Grade? Grade { get; set; } pubpc virtual Course Course { get; set; } [ForeignKey("StudentID")] pubpc virtual Student Student { get; set; } }
You can see now that the ForeignKey attribute is appped to the navigation property.
NotMapped
By 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. But this isn’t always the case in your apppcations. NotMapped attribute overrides this default convention. For example, you might have a property in the Student class such as FatherName, but it does not need to be stored. You can apply NotMapped attribute to a FatherName property which you do not want to create a column of in the database as shown in the following code.
pubpc class Student { [Key] pubpc int StdntID { get; set; } pubpc string LastName { get; set; } pubpc string FirstMidName { get; set; } pubpc DateTime EnrollmentDate { get; set; } [NotMapped] pubpc int FatherName { get; set; } pubpc virtual ICollection<Enrollment> Enrollments { get; set; } }
You can see that NotMapped attribute is appped to the FatherName property. When the table is generated you will see that FatherName column will not be created in a database, but it is present in Student class.
Code First will not create a column for a property, which does not have either getters or setters as shown in the following example of Address and Age properties of Student class.
InverseProperty
InverseProperty is used when you have multiple relationships between classes. In the Enrollment class, you may want to keep track of who enrolled a Current Course and Previous Course. Let’s add two navigation properties for the Enrollment class.
pubpc class Enrollment { pubpc int EnrollmentID { get; set; } pubpc int CourseID { get; set; } pubpc int StudentID { get; set; } pubpc Grade? Grade { get; set; } pubpc virtual Course CurrCourse { get; set; } pubpc virtual Course PrevCourse { get; set; } pubpc virtual Student Student { get; set; } }
Similarly, you’ll also need to add in the Course class referenced by these properties. The Course class has navigation properties back to the Enrollment class, which contains all the current and previous enrollments.
pubpc class Course { pubpc int CourseID { get; set; } pubpc string Title { get; set; } [Index] pubpc int Credits { get; set; } pubpc virtual ICollection<Enrollment> CurrEnrollments { get; set; } pubpc virtual ICollection<Enrollment> PrevEnrollments { get; set; } }
Code First creates {Class Name}_{Primary Key} foreign key column, if the foreign key property is not included in a particular class as shown in the above classes. When the database is generated, you will see the following foreign keys.
As you can see that Code first is not able to match up the properties in the two classes on its own. The database table for Enrollments should have one foreign key for the CurrCourse and one for the PrevCourse, but Code First will create four foreign key properties, i.e.
CurrCourse _CourseID
PrevCourse _CourseID
Course_CourseID, and
Course_CourseID1
To fix these problems, you can use the InverseProperty annotation to specify the apgnment of the properties.
pubpc class Course { pubpc int CourseID { get; set; } pubpc string Title { get; set; } [Index] pubpc int Credits { get; set; } [InverseProperty("CurrCourse")] pubpc virtual ICollection<Enrollment> CurrEnrollments { get; set; } [InverseProperty("PrevCourse")] pubpc virtual ICollection<Enrollment> PrevEnrollments { get; set; } }
As you can see the InverseProperty attribute is appped in the above Course class by specifying which reference property of Enrollment class it belongs to. Now, Code First will generate a database and create only two foreign key columns in Enrollments table as shown in the following image.
We recommend that you execute the above example in a step-by-step manner for better understanding.
Advertisements