005 Add EF and Create DB - CarrieKroutil/Reactivities GitHub Wiki
- Install extension NuGet Gallery | Publisher: pcislo
- [shift + command + p] to open command pallet and type
nuget
to “Open NuGet Gallery” - Search for package like “Microsoft.EntityFrameworkCore.Sqlite” -
- Check which project(s) to install. E.g. Persistence.csproj
- Select version that matches projects target framework
- Click “Install”
The following steps will add EF using code first database approach.
- In Domain project, add new Activity class -
namespace Domain
{
public class Activity
{
public Guid Id { get; set; }
public string Title { get; set; }
public DateTime Date { get; set; }
public string Description { get; set; }
public string Category { get; set; }
public string City { get; set; }
public string Venue { get; set; }
}
}
- In Persistence project, add new class - DataContext that inherits DbContext with default constructor:
using Domain;
using Microsoft.EntityFrameworkCore;
namespace Persistence
{
public class DataContext : DbContext
{
public DataContext(DbContextOptions options) : base(options)
{
}
public DbSet<Activity> Activities { get; set; }
}
}
-
In terminal, run dotnet restore - this will give the API project access to the newly added package.
-
In API project → Program.cs → Add:
builder.Services.AddDbContext<DataContext>(opt =>
{
opt.UseSqlite(builder.Configuration.GetConnectionString("DefaultConnection"));
});
- In API project → appsettings.Development.json → Add:
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=reactivities.db"
}
}
Above steps are considered code first, now let’s create a migration script to create database from code.
- In terminal, run
dotnet tool list -g
to see if you havedotnet-ef
installed globally (-g) and if it is on the current target framework.- If not installed, go to dotnet-ef and grab the .NET CLI script to run:
dotnet tool install --global dotnet-ef --version 9.0.0
.- After it runs, if using zsh, you can add it to your profile by running the following command:
- If not installed, go to dotnet-ef and grab the .NET CLI script to run:
cat << \EOF >> ~/.zprofile
# Add .NET Core SDK tools
export PATH="$PATH:/Users/carrie/.dotnet/tools"
EOF
- Run
zsh -l
to make it available for current session. - If it was already installed but an older version, just change the script above to use “update” in place of “install” and for the desired version.
- Run
dotnet ef
command to check it is working. - Add NuGet package:
Microsoft.EntityFrameworkCore.Design
into the API project. - This is required for the Entity Framework Core Tools work.
Above code steps are considered code first, next create a migration script to create database from code.
- Run
dotnet ef migrations add InitialCreate -s API -p Persistence
- Terminal should spit out: “Done. To undo this action, use
ef migrations remove
". - New “Migrations” folder should have been created in the Persistence project.
- Terminal should spit out: “Done. To undo this action, use
- Run
dotnet ef database
to see available commands.- Note: The update command will create db if one does not exist.
- Update API project’s Program.cs with below code to run before
app.Run();
:
using var scope = app.Services.CreateScope();
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<DataContext>();
await context.Database.MigrateAsync();
await Seed.SeedData(context);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occured during migration");
}
- In terminal,
cd API
then rundotnet watch
to start with hot reload. Database should now exist. - Database created and contains “__EFMigrationsHistory” table to show which scripts have been run.
- Press “Ctrl + R” to restart. Press “Ctrl+C” to shut down.
Now that database has been created, lets view it in SqLite.
- [shift + command + p] to open command pallet and type
sqlite
to “SQLite: Open Database”.- Select the newly created “reactivities.db” file.
- Though it appears nothing has happened, there is a new “SQLITE EXPLORER” menu now available from the File Explorer.
- In API project, create seed data class for database:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Domain;
namespace Persistence
{
public class Seed
{
public static async Task SeedData(DataContext context)
{
// Check if activities have already been created and stop.
if (context.Activities.Any()) return;
// Otherwise, create a list of activities to be added to the database.
var activities = new List<Activity>
{
new Activity
{
Title = "Past Activity 1",
Date = DateTime.UtcNow.AddMonths(-2),
Description = "Activity 2 months ago",
Category = "drinks",
City = "London",
Venue = "Pub",
},
new Activity
{
Title = "Past Activity 2",
Date = DateTime.UtcNow.AddMonths(-1),
Description = "Activity 1 month ago",
Category = "culture",
City = "Paris",
Venue = "Louvre",
},
new Activity
{
Title = "Future Activity 1",
Date = DateTime.UtcNow.AddMonths(1),
Description = "Activity 1 month in future",
Category = "culture",
City = "London",
Venue = "Natural History Museum",
},
new Activity
{
Title = "Future Activity 2",
Date = DateTime.UtcNow.AddMonths(2),
Description = "Activity 2 months in future",
Category = "music",
City = "London",
Venue = "O2 Arena",
},
new Activity
{
Title = "Future Activity 3",
Date = DateTime.UtcNow.AddMonths(3),
Description = "Activity 3 months in future",
Category = "drinks",
City = "London",
Venue = "Another pub",
},
new Activity
{
Title = "Future Activity 4",
Date = DateTime.UtcNow.AddMonths(4),
Description = "Activity 4 months in future",
Category = "drinks",
City = "London",
Venue = "Yet another pub",
},
new Activity
{
Title = "Future Activity 5",
Date = DateTime.UtcNow.AddMonths(5),
Description = "Activity 5 months in future",
Category = "drinks",
City = "London",
Venue = "Just another pub",
},
new Activity
{
Title = "Future Activity 6",
Date = DateTime.UtcNow.AddMonths(6),
Description = "Activity 6 months in future",
Category = "music",
City = "London",
Venue = "Roundhouse Camden",
},
new Activity
{
Title = "Future Activity 7",
Date = DateTime.UtcNow.AddMonths(7),
Description = "Activity 2 months ago",
Category = "travel",
City = "London",
Venue = "Somewhere on the Thames",
},
new Activity
{
Title = "Future Activity 8",
Date = DateTime.UtcNow.AddMonths(8),
Description = "Activity 8 months in future",
Category = "film",
City = "London",
Venue = "Cinema",
}
};
await context.Activities.AddRangeAsync(activities);
await context.SaveChangesAsync();
}
}
}
- Press “Ctrl + R” to restart. Though in .NET 7 it does not always work but appears it should have, don’t use and wait for .NET 8 to see if they fix it to work more accurately. So now press “Ctrl + C” to stop.
- Instead, use file watcher by running:
dotnet watch --no-hot-reload
.
- Instead, use file watcher by running:
- To view table with data, open “SQLITE EXPLORER” and click on the “play” button to the right of “Activities” database