- 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 - First Example
Let’s define a very simple model using classes. We’re just defining them in the Program.cs file but in a real-world apppcation you will sppt your classes into separate files and potentially a separate project. Following is a data model which we will be creating using Code First approach.
Create Model
Add the following three classes in Program.cs file using the following code for Student class.
pubpc class Student { pubpc int ID { get; set; } pubpc string LastName { get; set; } pubpc string FirstMidName { get; set; } pubpc DateTime EnrollmentDate { get; set; } pubpc virtual ICollection<Enrollment> Enrollments { get; set; } }
The ID property will become the primary key column of the database table that corresponds to this class.
The Enrollments property is a navigation property. Navigation properties hold other entities that are related to this entity.
In this case, the Enrollments property of a Student entity will hold all of the Enrollment entities that are related to that Student entity.
Navigation properties are typically defined as virtual so that they can take advantage of certain Entity Framework functionapty such as lazy loading.
If a navigation property can hold multiple entities (as in many-to-many or one-tomany relationships), its type must be a pst in which entries can be added, deleted, and updated, such as ICollection.
Following is the implementation for Course class.
pubpc class Course { pubpc int CourseID { get; set; } pubpc string Title { get; set; } pubpc int Credits { get; set; } pubpc virtual ICollection<Enrollment> Enrollments { get; set; } }
The Enrollments property is a navigation property. A Course entity can be related to any number of Enrollment entities.
Following is the implementation for Enrollment class and enum.
pubpc enum Grade { A, B, C, D, F } 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; } }
The EnrollmentID property will be the primary key.
The Grade property is an enum. The question mark after the Grade type declaration indicates that the Grade property is nullable.
A grade that s null is different from a zero grade. Null means a grade isn t known or hasn t been assigned yet.
The StudentID and CourseID properties are foreign keys, and the corresponding navigation properties are Student and Course.
An Enrollment entity is associated with one Student and one Course entity, so the property can only hold a single Student and Course entity.
Create Database Context
The main class that coordinates Entity Framework functionapty for a given data model is the database context class which allows to query and save data. You can create this class by deriving from the DbContext class and exposing a typed DbSet
pubpc class MyContext : DbContext { pubpc virtual DbSet<Course> Courses { get; set; } pubpc virtual DbSet<Enrollment> Enrollments { get; set; } pubpc virtual DbSet<Student> Students { get; set; } }
Following is the complete code in Program.cs file.
using System.ComponentModel.DataAnnotations.Schema; using System.Data.Entity; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EFCodeFirstDemo { class Program { static void Main(string[] args) {} } pubpc enum Grade { A, B, C, D, F } 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 { pubpc int ID { get; set; } pubpc string LastName { get; set; } pubpc string FirstMidName { get; set; } pubpc DateTime EnrollmentDate { get; set; } pubpc virtual ICollection<Enrollment> Enrollments { get; set; } } pubpc class Course { pubpc int CourseID { get; set; } pubpc string Title { get; set; } pubpc int Credits { get; set; } pubpc virtual ICollection<Enrollment> Enrollments { get; set; } } pubpc class MyContext : DbContext { pubpc virtual DbSet<Course> Courses { get; set; } pubpc virtual DbSet<Enrollment> Enrollments { get; set; } pubpc virtual DbSet<Student> Students { get; set; } } }
The above code is all we need to start storing and retrieving data. Let’s add some data and then retrieve it. Following is the code in main method.
static void Main(string[] args) { using (var context = new MyContext()) { // Create and save a new Students Console.WriteLine("Adding new students"); var student = new Student { FirstMidName = "Alain", LastName = "Bomer", EnrollmentDate = DateTime.Parse(DateTime.Today.ToString()) }; context.Students.Add(student); var student1 = new Student { FirstMidName = "Mark", LastName = "Upston", EnrollmentDate = DateTime.Parse(DateTime.Today.ToString()) }; context.Students.Add(student1); context.SaveChanges(); // Display all Students from the database var students = (from s in context.Students orderby s.FirstMidName select s).ToList<Student>(); Console.WriteLine("Retrieve all Students from the database:"); foreach (var stdnt in students) { string name = stdnt.FirstMidName + " " + stdnt.LastName; Console.WriteLine("ID: {0}, Name: {1}", stdnt.ID, name); } Console.WriteLine("Press any key to exit..."); Console.ReadKey(); } }
When the above code is executed, you will receive the following output.
Adding new students Retrieve all Students from the database: ID: 1, Name: Alain Bomer ID: 2, Name: Mark Upston Press any key to exit...
Now the question that comes to mind is, where is the data and the database in which we have added some data and then retrieved it from database. By convention, DbContext has created a database for you.
If a local SQL Express instance is available then Code First has created the database on that instance.
If SQL Express isn’t available, then Code First will try and use LocalDb.
The database is named after the fully quapfied name of the derived context.
In our case, SQL Express instance is available, and the database name is EFCodeFirstDemo.MyContext as shown in the following image.
These are just the default conventions and there are various ways to change the database that Code First uses.
As you can see in the above image, it has created Students, Courses and Enrollments tables and each table contains columns with appropriate datatype and length.
The column names and datatype also matches with the properties of the respective domain classes.
Database Initiapzation
In the above example, we have seen that Code First creates a database automatically, but if you want to change the name of the database and server, let us see how Code First decides the database name and server while initiapzing a database. Take a look at the following diagram.
You can define the base constructor of the context class in the following ways.
No Parameter
Database Name
Connection String Name
No Parameter
If you specify the base constructor of the context class without any parameter as shown in the above example, then entity framework will create a database in your local SQLEXPRESS server with a name {Namespace}.{Context class name}.
In the above example, the database which is created automatically has the name EFCodeFirstDemo.MyContext. If you look at the name, you will find that EFCodeFirstDemo is the namespace and MyContext is the context class name as shown in the following code.
pubpc class MyContext : DbContext { pubpc MyContext() : base() {} pubpc virtual DbSet<Course> Courses { get; set; } pubpc virtual DbSet<Enrollment> Enrollments { get; set; } pubpc virtual DbSet<Student> Students { get; set; } }
Database Name
If you pass the database name as a parameter in a base constructor of the context class, then Code First will create a database automatically again, but this time the name will be the one passed as parameter in the base constructor on the local SQLEXPRESS database server.
In the following code, MyContextDB is specified as parameter in the base constructor. If run your apppcation, then the database with MyContextDB name will be created in your local SQL server.
pubpc class MyContext : DbContext { pubpc MyContext() : base("MyContextDB") {} pubpc virtual DbSet<Course> Courses { get; set; } pubpc virtual DbSet<Enrollment> Enrollments { get; set; } pubpc virtual DbSet<Student> Students { get; set; } }
Connection String Name
This is an easy way to tell DbContext to use a database server other than SQL Express or LocalDb. You may choose to put a connection string in your app.config file.
If the name of the connection string matches the name of your context (either with or without namespace quapfication), then it will be found by DbContext when the parameter less constructor is used.
If the connection string name is different from the name of your context, then you can tell DbContext to use this connection in Code First mode by passing the connection string name to the DbContext constructor.
pubpc class MyContext : DbContext { pubpc MyContext() : base("name = MyContextDB") {} pubpc virtual DbSet<Course> Courses { get; set; } pubpc virtual DbSet<Enrollment> Enrollments { get; set; } pubpc virtual DbSet<Student> Students { get; set; } }
In the above code, snippet of context class connection string is specified as a parameter in the base constructor.
Connection string name must start with "name=" otherwise, it will consider it as a database name.
This form makes it exppcit that you expect the connection string to be found in your config file. An exception will be thrown if a connection string with the given name is not found.
<connectionStrings> <add name = "MyContextDB" connectionString = "Data Source =.;Initial Catalog = EFMyContextDB;Integrated Security = true" providerName = "System.Data.SqlCpent"/> </connectionStrings>
The database name in the connection string in app.config is EFMyContextDB. CodeFirst will create a new EFMyContextDB database or use existing EFMyContextDB database at local SQL Server.
Domain Classes
So far we’ve just let EF discover the model using its default conventions, but there are going to be times when our classes don’t follow the conventions and we need to be able to perform further configuration. But you can override these conventions by configuring your domain classes to provide EF with the information it needs. There are two options to configure your domain classes −
Data Annotations
Fluent API
Data Annotations
DataAnnotations is used to configure your 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 allow these apppcations to leverage the same annotations for cpent-side vapdations.
Following are the data annotations used in student class.
pubpc class Enrollment { [Key] pubpc int EnrollmentID { get; set; } pubpc int CourseID { get; set; } pubpc int StudentID { get; set; } pubpc Grade? Grade { get; set; } [ForeignKey("CourseID")] pubpc virtual Course Course { get; set; } [ForeignKey("ID")] pubpc virtual Student Student { get; set; } }
Fluent API
Most model configuration can be done using simple data annotations. The fluent API is a advanced way of specifying model configuration that covers everything that data annotations can do, in addition to some more advanced configuration not possible with data annotations. Data annotations and the fluent API can be used together.
To access the fluent API you override the OnModelCreating method in DbContext. Now let’s rename the column name in student table from FirstMidName to FirstName as shown in the following code.
pubpc class MyContext : DbContext { protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Student>().Property(s ⇒ s.FirstMidName) .HasColumnName("FirstName"); } pubpc virtual DbSet<Course> Courses { get; set; } pubpc virtual DbSet<Enrollment> Enrollments { get; set; } pubpc virtual DbSet<Student> Students { get; set; } }Advertisements