Skip to main content

why properties are defined as virtual in asp.net webapi

Navigation properties are typically defined as virtual so that they can take advantage of certain Entity Framework functionality such as lazy loading.

===============================================================================
Let’s define a very simple model using classes. We’re just defining them in the Program.cs file but in a real-world application you will split your classes into separate files and potentially a separate project. Following is a data model which we will be creating using Code First approach.
Model Using Classes

Create Model

Add the following three classes in Program.cs file using the following code for Student class.
public class Student {
   public int ID { get; set; }
   public string LastName { get; set; }
   public string FirstMidName { get; set; }
   public DateTime EnrollmentDate { get; set; }
 
   public 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 functionality 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 list in which entries can be added, deleted, and updated, such as ICollection.
Following is the implementation for Course class.
public class Course {
   public int CourseID { get; set; }
   public string Title { get; set; }
   public int Credits { get; set; }
 
   public 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.
public enum Grade {
   A, B, C, D, F
}

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; }
   public 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 functionality 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 for each class in our model. Following is the implementation on MyContext class, which is derived from DbContext class.
public class MyContext : DbContext {
   public virtual DbSet<Course> Courses { get; set; }
   public virtual DbSet<Enrollment> Enrollments { get; set; }
   public 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) {}
   }

   public enum Grade {
      A, B, C, D, F
   }

   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; }
      public virtual Student Student { get; set; }
   }

   public class Student {
      public int ID { get; set; }
      public string LastName { get; set; }
      public string FirstMidName { get; set; }
      public DateTime EnrollmentDate { get; set; }
  
      public virtual ICollection<Enrollment> Enrollments { get; set; }
   }

   public class Course {
      public int CourseID { get; set; }
      public string Title { get; set; }
      public int Credits { get; set; }
  
      public virtual ICollection<Enrollment> Enrollments { get; set; }
   }

   public class MyContext : DbContext {
      public virtual DbSet<Course> Courses { get; set; }
      public virtual DbSet<Enrollment> Enrollments { get; set; }
      public 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 qualified 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.
SQL Express Instance
  • 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 Initialization

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 initializing a database. Take a look at the following diagram.
Database Initialization
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.
public class MyContext : DbContext {
   public MyContext() : base() {}

   public virtual DbSet<Course> Courses { get; set; }
   public virtual DbSet<Enrollment> Enrollments { get; set; }
   public 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 application, then the database with MyContextDB name will be created in your local SQL server.
public class MyContext : DbContext {
   public MyContext() : base("MyContextDB") {}
   public virtual DbSet<Course> Courses { get; set; }
   public virtual DbSet<Enrollment> Enrollments { get; set; }
   public 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 qualification), 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.
public class MyContext : DbContext {
   public MyContext() : base("name = MyContextDB") {}
   public virtual DbSet<Course> Courses { get; set; }
   public virtual DbSet<Enrollment> Enrollments { get; set; }
   public 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 explicit 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.SqlClient"/>
</connectionStrings>
  • The database name in the connection string in app.config isEFMyContextDB. CodeFirst will create a new EFMyContextDBdatabase 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 highlight the most commonly needed configurations. DataAnnotations are also understood by a number of .NET applications, such as ASP.NET MVC which allow these applications to leverage the same annotations for client-side validations.
Following are the data annotations used in student class.
public class Enrollment {

   [Key]
   public int EnrollmentID { get; set; }
   public int CourseID { get; set; }
   public int StudentID { get; set; }
   public Grade? Grade { get; set; }

   [ForeignKey("CourseID")]
   public virtual Course Course { get; set; }

   [ForeignKey("ID")]
   public 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.
public class MyContext : DbContext {

   protected override void OnModelCreating(DbModelBuilder modelBuilder) {
      modelBuilder.Entity<Student>().Property(s  s.FirstMidName)
         .HasColumnName("FirstName");
   }

   public virtual DbSet<Course> Courses { get; set; }
   public virtual DbSet<Enrollment> Enrollments { get; set; }
   public virtual DbSet<Student> Students { get; set; }
}

Comments

Popular posts from this blog

What is cookie? Advantages and disadvantages of cookies?

What is cookie? A cookie is a small piece of text file stored on user's computer in the form of name-value pair. Cookies are used by websites to keep track of visitors e.g. to keep user information like username etc. If any web application using cookies, Server send cookies and client browser will store it. The browser then returns the cookie to the server at the next time the page is requested. The most common example of using a cookie is to store User information, User preferences, Password Remember Option etc.It is also one of the common and mostly asked interview questions. Some facts about Cookie Here are a few facts to know about cookies: · Cookies are domain specific i.e. a domain cannot read or write to a cookie created by another domain. This is done by the browser for security purpose. · Cookies are browser specific. Each browser stores the cookies in a different location. The cookies are browser specific and so a cookie created in one browser(e.g in Google Chrome

Code First Getting Started

In this tutorial let us create a simple application to demonstrate the use of entity framework using code first. We are using Visual Studio 2015 and entity framework 6.1.3. You can download Visual Studio community Edition . You should have the basic knowledge of .Net framework, C# and MS SQL Server. In this tutorial, we will create a simple application with a user class.  Our user class will have basic information like name and email address of the user. Create the Project Open Visual Studio. File ->New -> Project Select C# -> Select Console Application Name the application as “EFGettingStarted” Click on OK Install Entity Framework The next step is to install the Entity framework. This can be installed via nuget package console. Click on Tools->Nuget Package manager -> Package Manager Console and type the following command C# 1 2 3   install - package entityframework   This will install the late

First, FirstOrDefault, Single, SingleOrDefault In C#

For people who are new to LINQ, it is difficult to understand the difference between First, FirstOrDefault, Single, SingleOrDefault. In this blog, I will explain what to use and when.     I will take a simple example to make you understand practically how these methods work.   Consider a class Employee with properties as Id, Name, and Department. class  Employee {    public   int  Id {  get ;  set ; }    public   string  Name {  get ;  set ; }    public   string  Department{  get ;  set ; } } I have a list of Employees: List<Employee> employeeList =  new  List<Employee>(){    new  Employee() { Id = 1, Name =  "Sunny" , Department =  "Technical"  },    new  Employee() { Id=2, Name= "Pinki" , Department = "HR" },    new  Employee() { Id=3, Name= "Tensy" , Department = "Finance" },    new  Employee() { Id=4, Name= "Bobby" , Department = "Technical" },    new