First Experience with ASP.NET Core MVC & PostgreSQL

Goal

To build an ASP.NET Core 5 MVC web app linked with a PostgreSQL.

Motivation

  1. SQL Server is proprietary.
  2. SQLite used in Microsoft’s ASP.NET Core 5 MVC tutorial isn’t made for web apps.
  3. MySQL doesn’t perform well with concurrent read-writes. It’s dual-licensed like GitLab.
  4. Some users find PostgreSQL cost-effective.

Useful tutorials

  1. MS’s tutorial in item 2 above.
  2. Wes Doyle’s YouTube video goes through the steps
  3. MS’s tutorial for Razor Pages with EF Core migrations

Steps

  1. Create a superuser in the database.

    sudo -u postgres psql
    

    By default the user postgres is the admin of the DBMS.

    CREATE USER mydev WITH SUPERUSER;
    ALTER USER mydev WITH PASSWORD 'my0eV';
    

    Then we go to pgAdmin and grant super user mydev all privileges.

  2. dotnet mvc -o Foo

  3. Create framework-independent model Models/Movie.cs.

    using System;
    using System.ComponentModel.DataAnnotations;
    
    namespace Foo.Models
    {
        public class Movie
        {
            public int Id { get; set; }
            public string Title { get; set; }
    
            [DataType(DataType.Date)]
            public DateTime ReleaseDate { get; set; }
            public string Genre { get; set; }
            public decimal Price { get; set; }
        }
    }
    
  4. Add necessary NuGet Packages.

    dotnet tool install --global dotnet-ef
    dotnet add package Microsoft.EntityFrameworkCore.Tools
    dotnet add package Microsoft.EntityFrameworkCore.Tools.Dotnet
    dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
    

    The Foo.csproj file will automatically get updated.

  5. Create a database context class Data/MovieContext.cs. It’s responsible for connecting the database with the app.

    using Microsoft.EntityFrameworkCore;
    using Foo.Models;
    
    namespace Foo.Data
    {
        public class MvcMovieContext : DbContext
        {
            public MvcMovieContext (DbContextOptions<MvcMovieContext> options)
                : base(options)
            {
            }
    
            protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            => optionsBuilder
                .UseNpgsql("Host=localhost;Port=5432;Database=MvcMovie;Username=mydev;Password=my0eV;Integrated Security=true;Pooling=true")
                .UseSnakeCaseNamingConvention();
    
            public DbSet<Movie> Movies { get; set; }
        }
    }
    

    The UseSnakeCaseNamingConvention method converts ReleaseDate in the model class to release_date in the final database.

    DbSet<TE> TEs is a space to hold instances of TEs.

    I got stuck by mistakingly putting the OnConfiguring method inside the constructor.

  6. Startup settings. In the Startup.ConfigureServices method, register the database context with the service during app startup.

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
    
        services.AddDbContext<MvcMovieContext>(options =>
                options.UseNpgsql(Configuration.GetConnectionString("MvcMovieContext")));
    }
    

    At the top of Startup.cs, we add two packages.

    using Microsoft.EntityFrameworkCore;
    using Foo.Data;
    

    There’s no need to import Npgsql.EntityFrameworkCore.PostgreSQL. The package import in the Foo.csproj file in step 3 will do.

  7. Add the ConnectionStrings in appsettings.json. In the YouTube videos, it appears as Server and User Id, but after a code search in the package’s GitHub repo, I’m convinced that the documented connection strings parameters are valid.

    "AllowedHosts": "*",
      "ConnectionStrings": {
        "MvcMovieContext": "Host=localhost;Port=5432;Database=MvcMovie;Username=mydev;Password=my0eV;Integrated Security=true;Pooling=true"
    }
    
  8. Execute the following two commands. The build should succeed in seconds.

    dotnet ef migrations add InitialCreate
    dotnet ef database update
    
    command tool dotnet-ef succeeded

    I forgot to install dotnet-ef, so those two didn’t run at first.

  9. A new database MvcMovie is generated. The table movies is empty. Observe that the columns are in snake case: ReleaseDate in the model class file is converted to release_date. That’s a common practice in PostgreSQL.

    EFMigrationHistory table shows migration details
    The generated database with column in snake case

Source code

View the related commit.


1 comment

Your email address will not be published. Required fields are marked *.