The Entity Framework Code First approach allows us to create a model as a plain class and then the database gets created from the domain model or entity class. In the Code First approach, the database gets created from the classes.
Some advantages of the Entity Framework Code First approach include (as stated in Scott Gu’s blog):
• Developing without ever having to open a designer or define an XML mapping file
• Defining your model objects by simply writing “plain old classes” with no base classes required
• Using a “convention over configuration” approach that enables database persistence without explicitly configuring anything
• Optionally overriding the convention-based persistence and using a fluent code API to fully customize the persistence mapping
Rather the delving more into theoretical concepts, in this post we will directly jump into code and create a table and database using the Code First approach. In this post we will learn how we can create entities and a relationship between entities in the Entity Framework Code First approach. In the EF Code First approach, there are two options to create the relationship between entities, through:
1. Data annotations
2. Fluent API
In this post we will use data annotations to create the relationship between entities.
Create database with one table
Let us start with creating a table named Student in a database with the code first approach. The domain class Student can be created as shown in the listing below:
namespace CodeFirstDemoApp
{
publicclassStudent
{
publicint Id { get; set; }
publicstring Name { get; set; }
publicint Age { get; set; }
}
}
As you might have already noticed, the Student class is a plain class. Entity Framework will use the Student class to create the table in the database. The Student class represents the domain entity and it should not have any information or references of the database. Entity Framework will use the Student class to create the Student table.
Once the domain entity class is created, next we need to create a Context class which will inherit the DataContext class. The context class can be created as shown in the listing below:
using System.Data.Entity;
namespace CodeFirstDemoApp
{
publicclassContext : DbContext
{
public Context() : base()
{
}
publicDbSet<Student> Students { get; set; }
}
}
We have created the Context class with the default constructor. Later in the post we will talk about various options in the constructor. In the context class we are doing the following tasks:
· Creating the default constructor. Since we are not passing any parameter in the constructor, so the EF will create a database with the name as Namespace.Class name. So in this case, the created database name will be CodeFirstDemo.Context.
· Since we are not passing a connection string information in the constructor of Context class, the EF will create a database in the default database server of SQL Server Express.
· To create a database in the desired server with the desired name, we need to create the connection string and pass that as a parameter in the Context constructor.
· To create the table in the database, create a public property of the generic DbSet type with domain entity passed in it.
So far we have created the Student entity class and the Context class. Now we can write a simple LINQ to Entity query to create the database and perform the operations as shown in the listing below:
using System;
using System.Linq;
namespace CodeFirstDemoApp
{
classProgram
{
staticvoid Main(string[] args)
{
CreateStudent();
Console.WriteLine("Student Creatred");
Context c = newContext();
var result = from r in c.Students select r;
foreach (var r in result)
{
Console.WriteLine(r.Name);
}
Console.ReadKey(true);
}
staticvoid CreateStudent()
{
Student s = newStudent
{
Id = 1,
Age = 12,
Name = "Foo"
};
Context c = newContext();
c.Students.Add(s);
c.SaveChanges();
}
}
}
Custom database name
When we work with the default constructor for the Context class, EF by default creates the database with a fully qualified name as Namespace.Contextclass name. However we can pass the desired name of the database mydb in this case in the constructor as shown in the listing below:
public Context()
: base("mydb")
{
}
In the SQL Express EF will create a database with the name mydb.
Working with Connection String
As of now we are relying on the EF to create the database. However we can pass a connection string to create a database at the desired server and a name. The connection string can be created in the config file as listed below:
<connectionStrings>
<addname="democonnectionstring"connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=Demo1;Integrated Security=True;MultipleActiveResultSets=true"providerName="System.Data.SqlClient"/>
</connectionStrings>
We have created a connection string to create a database in local db server. Next we need to pass the connection string name in the constructor of Context class as shown in the listing below:
public Context()
: base("name=democonnectionstring")
{
}
Relationship between Entities
In the Code First approach, we can create a relationship between entities using either of the two options:
1. Data Annotations
2. Fluent API
In this post we will create relationship using data annotations.
One to One Relationship
We may have a requirement to create one to one relationships between two entities. In other words, we need a Primary key – Foreign Key relationship between two entities. Let us say we have two entities and the following rules:
1. There are two entities named Student and StudentAccount
2. Student is a primary entity
3. StudentAccount is a dependent entity on Student
4. Primary key of StudentAccount will be foreign key of Student
We should not able to create a StudentAccount without a Student and there can only be one entry of Student in StudentAccount. Put simply, each Student will have one StudentAccount and no StudentAccount will exist without a Student.
Let us first create the primary entity: Student
publicclassStudent
{
publicint Id { get; set; }
publicstring Name { get; set; }
publicint Age { get; set; }
publicvirtualStudentAccount StudentAccount { get; set; }
}
As you might have noticed, in the Student entity we have a virtual property of the type StudentAccount which is created as shown the listing below:
publicclassStudentAccount
{
publicint Id { get; set; }
publicstring Name { get; set; }
publicint Amount { get; set; }
[Required]
publicvirtualStudent Student { get; set; }
}
Again you might have noticed that in the StudentAccount entity we have a virtual property of the type Student. Since Student is a primary entity, the virtual Student property in the StudentAccount entity is annotated Required. Further, a Context class can be created as shown in the listing below:
using System.Data.Entity;
namespace CodeFirstDemoApp
{
publicclassContext : DbContext
{
public Context()
: base("name=democonnectionstring")
{
}
publicDbSet<Student> Students { get; set; }
publicDbSet<StudentAccount> StudentAccounts{ get; set; }
}
}
Always remember that we cannot create a row in the StudentAccounts table unless we do not have a corresponding row in the Student table. Data can be created in the related table as shown in the listing below:
staticvoid CreateStudent()
{
Student s = newStudent
{
Id = 1,
Age = 12,
Name = "Foo"
};
StudentAccount sa = newStudentAccount
{
Amount = 300,
Name = "Sports Account",
Student = s
};
Context c = newContext();
c.Students.Add(s);
c.StudentAccounts.Add(sa);
c.SaveChanges();
}
As you might have noticed, we are setting the object of Student as a property of StudentAccount. We can retrieve records from both the tables as shown in the listing below:
Context c = newContext();
var result = from r in c.Students select r;
foreach (var r in result)
{
Console.WriteLine(r.Name);
Console.WriteLine(r.StudentAccounts.Amount);
}
To verify the relationship between entities in SQL Server Management Studio, we can see the columns created with the constraints and keys as shown in the image below:
Here the Id column of the StudentAccounts table is both the primary key and foreign key.
One to Many Relationship
We may have a requirement to create one too many relationship between two entities. Let us say we have two entities
1. There are two entities Student and StudentAddress
2. Student is a primary entity
3. StudentAddress is a dependent entity on Student
4. One Student can enroll in multiple StudentAddress
One Student can have many StudentAddress. One of the column of StudentAddress will have foreign key as primary key of Student.
Let us first create the primary entity Student,
publicclassStudent
{
public Student()
{
StudentAddresses = newHashSet<StudentAddress>();
}
publicint Id { get; set; }
publicstring Name { get; set; }
publicint Age { get; set; }
publicICollection<StudentAddress> StudentAddresses { get; set; }
}
You might have noticed that we are creating a property of collection of StudentAddress and then creating a set value of the StudentAddress property in the constructor of Student. The StudentAddress class can be created as shown in the listing below:
publicclassStudentAddress
{
publicint Id { get; set; }
publicstring Address { get; set;}
publicint StudentId { get; set; }
publicvirtualStudent Student { get; set; }
}
Again you might have noticed that in the StudentAddress entity we have a virtual property of the type Student. Since Student is a primary entity, the virtual Student property in the StudentAddress has a corresponding StudentId property.
Further, the Context class can be created as shown in the listing below:
publicclassContext : DbContext
{
public Context()
: base("name=democonnectionstring")
{
}
publicDbSet<Student> Students { get; set; }
publicDbSet<StudentAddress> StudentAddresses { get; set; }
}
Always remember that we cannot create a row in the StudentAddress table unless we do not have a corresponding row in the Student table. Data can be created in the related table as shown in the listing below:
staticvoid CreateStudent()
{
Student s = newStudent
{
Id = 1,
Age = 12,
Name = "Foo"
};
StudentAddress sa1 = newStudentAddress { Address = "Delhi", Id = 1 };
StudentAddress sa2 = newStudentAddress { Address = "Bangalore", Id = 2 };
s.StudentAddresses.Add(sa1);
s.StudentAddresses.Add(sa2);
Context c = newContext();
c.Students.Add(s);
c.SaveChanges();
}
As you might have noticed, we are adding the objects of StudentAddress to the Student. We can retrieve records from both tables as shown in the listing below:
staticvoid Main(string[] args)
{
CreateStudent();
Console.WriteLine("Student Created");
Context c = newContext();
var result = from r in c.Students.Include("StudentAddresses") select r;
foreach (var r in result)
{
Console.WriteLine(r.Name);
foreach(var a in r.StudentAddresses)
{
Console.WriteLine(a.Address);
}
}
Console.ReadKey(true);
}
To verify the relationship between entities in SQL Server Management Studio, we can see the columns created with the constraints and keys as shown in the image below:
Many to Many Relationship
Last but not least, let us see how we can configure a many to many relationship. Let’s say we have a Student entity and a Subject entity. One Student can be enrolled in many Subjects and One Subject can have many Students. To create a many too many relationship between these entities, let us first create the Student entity as shown in the listing below:
publicclassStudent
{
public Student()
{
Subjects = newHashSet<Subject>();
}
publicint Id { get; set; }
publicstring Name { get; set; }
publicint Age { get; set; }
publicICollection<Subject> Subjects { get; set; }
}
Here we’re creating a property of collection of Subjects and then creating a set value of the Subjects property in the constructor of Student. The Subject class can be created as shown in the listing below:
publicclassSubject
{
public Subject()
{
Students = newHashSet<Student>();
}
publicint Id { get; set; }
publicstring Name { get; set; }
publicvirtualICollection<Student> Students { get; set; }
}
In the Subject class also we are creating property of collection of Students and in the constructor of Subject class creating a set of students. This is all we need to do to create a many too many relationship between entities.
Further, the Context class can be created as shown in the listing below:
publicclassContext : DbContext
{
public Context()
: base("name=democonnectionstring")
{
}
publicDbSet<Student> Students { get; set; }
publicDbSet<Subject> Subjects { get; set; }
}
We can create the rows in the Students and Subjects table as shown in the listing below:
staticvoid CreateStudent()
{
Student s = newStudent
{
Id = 1,
Age = 12,
Name = "Foo"
};
Subject s1 = newSubject { Id = 1, Name = "Phy" };
Subject s2 = newSubject { Id = 2, Name = "Maths" };
s.Subjects.Add(s1);
s.Subjects.Add(s2);
Context c = newContext();
c.Students.Add(s);
c.SaveChanges();
}
We can retrieve records from both the tables as shown here:
staticvoid Main(string[] args)
{
CreateStudent();
Console.WriteLine("Student Created");
Context c = newContext();
var result = from r in c.Students.Include("Subjects") select r;
foreach (var r in result)
{
Console.WriteLine(r.Name);
foreach(var a in r.Subjects)
{
Console.WriteLine(a.Name);
}
}
Console.ReadKey(true);
}
When we verify the relationship between the Student and Subject entity, we will find that EF has created an extra table to maintain the many to many relationship
So there you have it, that’s how to create relationships between entities in the Code First approach. In this post we started with working with single entities and then proceeded to create a relationship between the entities. I hope you find this post useful, thanks for reading.
Infragistics Ultimate 15.2 is here. Download and see its power in action!