To get started a new project wich depends upon Entity Framework there are some preliminar steps to follow. First of all, we have to install all these following packages, paying attention of the database you want to use.
- Initial project configuration
- Scaffolding existing database
- Initial project configuration
- Scaffolding existing database (Database First)
- Create from the scratch (Code First)
- Visual studio code
- This project uses the Sakila database, available from mysql site used for demo purpose. If you want to follow this guide step-by-step, you can download Sakila db from here.
dotnet add package
- is the command that adds a package reference to a project file.
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.Tools
dotnet add package Microsoft.EntityFrameworkCore.Tools.DotNet
dotnet add package Pomelo.EntityFrameworkCore.MySql
dotnet add package Pomelo.EntityFrameworkCore.MySql.Design
Note: Remember to change in your *Project.csproj
these lines
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.1" />
in:
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.1" />
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.1" />
In order to scaffold (wich means: get my database structure and convert it into some classes in my project), you have to launch this command:
dotnet ef dbcontext scaffold "server=192.168.42.128;userid=root;pwd=d0808!;port=3306;database=sakila" Pomelo.EntityFrameworkCore.MySql -o Entites
Analyzing this command we could say:
dotnet ef dbcontext scaffold "<MY DATABASE CONNECTION STRING>" <THE PROVIDER> <-o WHERE TO PLACE THE OUTPUT> <MY FOLDER>
The classes generated from the migration now appears like this:
public partial class sakilaContext : DbContext
{
public virtual DbSet<Actor> Actor { get; set; }
public virtual DbSet<Address> Address { get; set; }
public virtual DbSet<Category> Category { get; set; }
// Hidden for brevity
In order to pluralize in all project these property without generate any errors, rename them selecting the property and pressing F2.
Then the expected class should appear like:
public partial class sakilaContext : DbContext
{
public virtual DbSet<Actor> Actors { get; set; }
public virtual DbSet<Address> Addressess { get; set; }
public virtual DbSet<Category> Categories { get; set; }
// Hidden for brevity
To initialize our database wich we'll use in our application, is sufficient to instantiate the class generated by the scaffolding. The name of the class we will use is the one wich contains the *Context.cs"
suffix. Then do as follow:
// Program.cs
static void Main(string[] args)
{
var context = new sakilaContext();
var movies = context.Films;
foreach (var movie in movies)
{
Console.WriteLine($"- {movie.Title}");
}
Console.WriteLine($"{movies.Count()} found.");
}
At this point, we can operate on the database very easly without worry about how about our application is communicating with the database.
We want to create this structure in our database from our code.
We can imagine these tables as classes, as is follow:
// The Student Entity Class
///////////////////////////
public class Student
{
public int ID { get; set; } //this is the primary key of the Student table
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
//Enrollments is a navigation property to gold enrollment data found in an other table
public ICollection<Enrollment> Enrollments { get; set; }
}
The ID
property rapresents the primary key of the class wich will reflects in the table.
Note: in some example you will find in the internet you will notice that someone it used to write
classnameID
. It's a best practice to leave theID
property asID
without any class name, in order to have a good inheritance implementation.
The collections in the classes are named Navigation property.
As you will notice, there is an attribute on top of the class Course
named [DatabaseGenerated(DatabaseGeneratedOption.None)]
. This attribute lets you to enter the primary key if isn't generated.
After create the SchoolContext
, it's time to create the mappers.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Course>().ToTable("Course");
modelBuilder.Entity<Enrollment>().ToTable("Enrollment");
modelBuilder.Entity<Student>().ToTable("Student");
}
There are 2 methods of creating the model with model builder:
- Fluent Api: wich is the best, because it permits you to configure your table without modify your entity classes;
//example of Fluent API
class MyContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.Property(b => b.Url)
.IsRequired();
}
}
- Data annotations: wich modify your entities but should be overwritten by Fluent Api modifications.
public class Blog
{
public int BlogId { get; set; }
[Required]
public string Url { get; set; }
}
See the example: https://youtu.be/vLwAfE2Q6wI