Introduction
Welcome to our blog post, where we'll explore the two primary approaches of Entity Framework Core (EF Core): Code First and Database First. EF Core, developed by Microsoft, simplifies the process of building database applications, as we discussed in a previous post. In this article, we'll delve into the concepts of Code First and Database First, and provide examples of implementing each approach. So let's get started!
Code First Approach in Entity Framework Core
The Code First approach in EF Core involves designing and coding the model classes first, and then letting EF Core create the corresponding database or tables based on those classes.
To demonstrate this approach, let's use the same structure we explored in our previous post on Database First. You can find all the code examples on GitHub.
Implementing Code First with EF Core
First, we need to create a class for each table in our database. In this case, we'll create two entities:
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
}
public class JobExperience
{
public int Id { get; set; }
public int UserId { get; set; }
[MaxLength(50)]
public string Name { get; set; }
public string Details { get; set; }
public string Environment { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
}
As you can see, you can include annotations on properties. In this case, we have set a maximum length of 50 characters for the "Name" column in the database.
Next, we install the Microsoft.EntityFrameworkCore.Design
package and the MySQL package since we are using MySQL for our database. If you're using a different database like SQL Server, you'll need to install the appropriate package. Refer to the documentation for more information.
Then, we create a class that inherits from DbContext
and defines the database instance and the tables it contains:
public class ExampleEFContext : DbContext
{
public virtual DbSet<User> Users { get; set; }
public virtual DbSet<JobExperience> JobExperiences { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseMySQL("server=127.0.0.1;port=4306;database=exampleEF;user=root;password=exampleEFpass");
}
}
In the DbContext
class, we configure the tables and the database connection. However, it is recommended to configure this in the Startup.cs
file for better separation of concerns. For simplicity, we've included it here.
Once we have everything set up, we can create the database. One option is to execute the code when the program runs, ensuring that the database is created if it doesn't already exist:
using (var scope = app.Services.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<ExampleEFContext>();
context.Database.EnsureCreated();
}
Now, let's take a look at the result:
As you can see, the "Name" column has the specified varchar length limit of 50 characters from the annotation.
The EnsureCreated
method is useful for quickly setting up the database, especially during the initial development phase of a project. However, we'll modify this code when we explore migrations in future posts.
Database First Approach in Entity Framework Core
This section covers how to use the "Database First" approach in EF Core. If you're unfamiliar with Entity Framework, it is a Microsoft framework that simplifies database application development, as we discussed in a previous post.
What is Database First?
The Database First approach means creating the database first and then generating the EF Core model (classes) based on that database. This approach is useful when you already have an existing database or when you want more control over the database structure.
Implementing Database First with EF Core
Before we proceed with the implementation, let's create the database. In this example, we'll use MySQL through Docker, but this approach works with any relational database. The only change required is the connection string in the C# code.
First, create the database and the tables. In this case, we'll create two tables with a relationship between them:
CREATE DATABASE IF NOT EXISTS `exampleEF`;
USE `exampleEF`;
CREATE TABLE IF NOT EXISTS `users` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`UserName` varchar(50) NOT NULL,
PRIMARY KEY (`Id`),
UNIQUE KEY `UserName` (`UserName`)
);
CREATE TABLE IF NOT EXISTS `jobexperiences` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`UserId` int(11) NOT NULL,
`Name` varchar(150) NOT NULL,
`Details` varchar(5000) NOT NULL,
`Environment` varchar(500) NOT NULL,
`StartDate` date DEFAULT NULL,
`EndDate` date DEFAULT NULL,
PRIMARY KEY (`Id`),
FOREIGN KEY (`UserId`) REFERENCES `users`(`Id`)
);
Now, let's import the entities from the database using EF Core. First, install the Microsoft.EntityFrameworkCore.Design
package:
dotnet add package Microsoft.EntityFrameworkCore.Design
If you're using a different database, such as MariaDB or SQL Server, the packages you need to install will be different. Refer to the documentation for the specific packages for your database.
Once the package is installed, run the following command to scaffold the entities using EF Core:
dotnet ef dbcontext scaffold "server=127.0.0.1;port=3306;database=exampleEF;user=exampleEFuser;password=exampleEFpass" MySql.EntityFrameworkCore -o Models
In the above command, replace the connection string with the appropriate one for your database. The -o Models
option specifies the location where the generated classes will be placed.
After the command completes, you'll see the generated classes, including the DbContext
that represents the database and a DbSet
for each table.
Finally, we can improve the default implementation of EF Core. By default, the connection string is present within the DbContext
, but this is not secure and will trigger a warning. We need to configure the DbContext
within the dependency container, which can be done in the Startup.cs
or Program.cs
file, depending on your .NET version. Ideally, the connection should be stored in a configuration file or a credentials vault. Here's an example:
builder.Services.AddDbContext<ExampleEFContext>(options =>
options.UseMySQL(builder.Configuration.GetConnectionString("exampleEF")
?? throw new Exception("Missing connection string")));
With this configuration, we can remove the OnConfiguring
method from our DbContext
.
Conclusion
In this blog post, we explored the Code First and Database First approaches in Entity Framework Core. The Code First approach allows us to design and code the model classes, while EF Core takes care of creating the corresponding database. On the other hand, the Database First approach involves creating the database first and generating the model classes from it.
Both approaches have their merits, and the choice depends on your project requirements and preferences. Whether you prefer starting with code or an existing database, Entity Framework Core provides powerful features and simplifies the development process. Stay tuned for more articles as we delve deeper into Entity Framework Core in future posts!