DEV Community

Cover image for Entity Framework Core Code First
Mohammed Chami
Mohammed Chami

Posted on • Edited on

2

Entity Framework Core Code First

Entity Framework Core: Code-First Approach and CRUD Operations

Entity Framework (EF) Core is a modern, lightweight, and extensible object-relational mapper (ORM) for .NET. It enables developers to work with databases using .NET objects, eliminating the need for most of the data-access code typically required. EF Core supports the code-first approach, where you define your database schema using C# classes and let EF Core handle the database creation and updates.


Key Features of EF Core

  1. Database Creation, Update, and Maintenance: EF Core can create and update the database schema based on your C# classes.
  2. LINQ Queries: Write type-safe queries using LINQ (Language Integrated Query) to retrieve data.
  3. Change Tracking: Automatically tracks changes to entities and persists them in the database.
  4. Schema Migrations: Easily evolve your database schema over time using migrations.

Supported Databases

EF Core works with a wide range of databases, including:

  • SQL Server
  • Azure SQL Database
  • SQLite
  • Azure Cosmos DB
  • MySQL
  • PostgreSQL
  • And other databases through a provider plugin API.

For a complete list of supported databases, refer to the official EF Core documentation.


Getting Started with EF Core Code-First

Step 1: Set Up Your Project

  1. Launch Visual Studio and create a new solution with a project.
  2. Add a Class Library named DataAccess to the solution. This library will contain your EF Core models and database context.

Step 2: Define Your Models

In the DataAccess library, create a folder (e.g., Models) and add two classes: Manufacturer and Product. These classes represent the entities in your database.

public class Manufacturer
{
    [Key]
    public int Id { get; set; }

    [Required]
    [StringLength(100)]
    public string Name { get; set; }

    [StringLength(200)]
    public string Description { get; set; }

    public string ContactEmail { get; set; }
    public string ContactPhone { get; set; }

    public virtual ICollection<Product> Products { get; set; } = new List<Product>();
}
Enter fullscreen mode Exit fullscreen mode
public class Product
{
    [Key]
    public int Id { get; set; }

    [Required]
    [StringLength(100)]
    public string Name { get; set; }

    [StringLength(500)]
    public string Description { get; set; }

    [Required]
    [Column(TypeName = "decimal(18,2)")]
    public decimal Price { get; set; }

    public int ManufacturerId { get; set; }

    [ForeignKey(nameof(ManufacturerId))]
    public virtual Manufacturer Manufacturer { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Install EF Core Packages

In the DataAccess library, install the following NuGet packages:

  • Microsoft.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore.SqlServer (or the provider for your database)
  • Microsoft.EntityFrameworkCore.Design
  • Microsoft.EntityFrameworkCore.Tools

You can install these packages via the NuGet Package Manager or the Package Manager Console:

Install-Package Microsoft.EntityFrameworkCore
Install-Package Microsoft.EntityFrameworkCore.SqlServer
Install-Package Microsoft.EntityFrameworkCore.Design
Install-Package Microsoft.EntityFrameworkCore.Tools
Enter fullscreen mode Exit fullscreen mode

Step 4: Create the Database Context

In the DataAccess library, create a class that inherits from DbContext. This class will manage your entities and database interactions.

public class ApplicationDbContext : DbContext
{
    public DbSet<Manufacturer> Manufacturers { get; set; }
    public DbSet<Product> Products { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(
            @"Server=MED;Database=testDB;Integrated Security=True");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Manufacturer>()
            .HasMany(m => m.Products)
            .WithOne(p => p.Manufacturer)
            .HasForeignKey(p => p.ManufacturerId)
            .OnDelete(DeleteBehavior.Restrict);
    }
}
Enter fullscreen mode Exit fullscreen mode

Note: The [NotMapped] attribute is not needed for navigation properties. EF Core will automatically ignore these properties when creating the database schema. The [NotMapped] attribute is typically used for properties that should not be persisted in the database. I wanted to mention this because I see people adding it which is not necessary.

Connection String and Security:

  • A connection string contains the server name, database name, and security credentials.
  • Store connection strings securely using:
    • Environment Variables
    • Secret Manager Tool (for development)
    • Azure Key Vault (for production)

Step 5: Create and Apply Migrations

  1. Open the Package Manager Console in Visual Studio.
  2. Set the default project to DataAccess.
  3. Run the following commands:
   Add-Migration Initial
   Update-Database
Enter fullscreen mode Exit fullscreen mode
  • Add-Migration Initial generates the migration scripts.
  • Update-Database applies the migration to the database.

EF Core will create the Manufacturer and Product tables, as well as a __EFMigrationsHistory table to track migrations.


Step 6: Perform CRUD Operations

Now that the database is set up, you can perform CRUD operations using the ApplicationDbContext.

Adding a Manufacturer:

using (var db = new ApplicationDbContext())
{
    var manufacturer = new Manufacturer
    {
        Name = "Manu_Toys",
        Description = "Creates kids' toys"
    };

    db.Manufacturers.Add(manufacturer);
    db.SaveChanges();
}
Enter fullscreen mode Exit fullscreen mode

Reading Data:

using (var db = new ApplicationDbContext())
{
    var manufacturers = db.Manufacturers.ToList();
    foreach (var manufacturer in manufacturers)
    {
        Console.WriteLine($"Manufacturer: {manufacturer.Name}");
    }
}
Enter fullscreen mode Exit fullscreen mode

Updating Data:

using (var db = new ApplicationDbContext())
{
    var manufacturer = db.Manufacturers.Find(1); // Find by Id
    if (manufacturer != null)
    {
        manufacturer.Description = "Updated description";
        db.SaveChanges();
    }
}
Enter fullscreen mode Exit fullscreen mode

Deleting Data:

using (var db = new ApplicationDbContext())
{
    var manufacturer = db.Manufacturers.Find(1); // Find by Id
    if (manufacturer != null)
    {
        db.Manufacturers.Remove(manufacturer);
        db.SaveChanges();
    }
}
Enter fullscreen mode Exit fullscreen mode

Best Practices

Note that this is just a simple example to show you EF Core Code First in a real project you would use the following:

  1. Use Dependency Injection: Inject DbContext into your services or controllers instead of creating instances manually.
  2. Async Operations: Use SaveChangesAsync and ToListAsync for better performance in web applications.
  3. Separate Concerns: Keep your data access logic in a separate layer (e.g., a repository pattern).

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)

Heroku

Build apps, not infrastructure.

Dealing with servers, hardware, and infrastructure can take up your valuable time. Discover the benefits of Heroku, the PaaS of choice for developers since 2007.

Visit Site

👋 Kindness is contagious

Immerse yourself in a wealth of knowledge with this piece, supported by the inclusive DEV Community—every developer, no matter where they are in their journey, is invited to contribute to our collective wisdom.

A simple “thank you” goes a long way—express your gratitude below in the comments!

Gathering insights enriches our journey on DEV and fortifies our community ties. Did you find this article valuable? Taking a moment to thank the author can have a significant impact.

Okay