🏗️ Initialize Db migration + DbInitializer (TrainingDb)

features/training-svc
Leo TUAILLON 9 hours ago
parent 2c791baa06
commit f45ba72569

@ -20,4 +20,8 @@
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.11" />
</ItemGroup>
<ItemGroup>
<Folder Include="Entities\" />
</ItemGroup>
</Project>

@ -27,7 +27,7 @@ public class ExercicesController : ControllerBase
[AllowAnonymous]
public async Task<IActionResult> Create([FromBody] CreateExerciceTemplateDto dto)
{
var exercice = _mapper.Map<Exercice>(dto);
var exercice = _mapper.Map<ExerciceTemplate>(dto);
_context.Exercices.Add(exercice);
await _context.SaveChangesAsync();
return CreatedAtAction(nameof(GetById), new { id = exercice.Id }, _mapper.Map<ExerciceTemplateDto>(exercice));

@ -9,5 +9,5 @@ public class CatalogDbContext : DbContext
{
}
public DbSet<Exercice> Exercices { get; set; }
public DbSet<ExerciceTemplate> Exercices { get; set; }
}

@ -22,9 +22,9 @@ public class DbInitializer
return;
}
var exercices = new List<Exercice>()
var exercices = new List<ExerciceTemplate>()
{
new Exercice
new ExerciceTemplate
{
Id = Guid.NewGuid().ToString(),
Name = "Squat",
@ -33,7 +33,7 @@ public class DbInitializer
ImageUrl = "images/squat.jpg",
VideoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley",
},
new Exercice
new ExerciceTemplate
{
Id = Guid.NewGuid().ToString(),
Name = "Bench Press",
@ -42,7 +42,7 @@ public class DbInitializer
ImageUrl = "images/bench_press.jpg",
VideoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley",
},
new Exercice
new ExerciceTemplate
{
Id = Guid.NewGuid().ToString(),
Name = "Deadlift",
@ -51,7 +51,7 @@ public class DbInitializer
ImageUrl = "images/deadlift.jpg",
VideoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley",
},
new Exercice
new ExerciceTemplate
{
Id = Guid.NewGuid().ToString(),
Name = "Shoulder Press",
@ -60,7 +60,7 @@ public class DbInitializer
ImageUrl = "images/shoulder_press.jpg",
VideoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley",
},
new Exercice
new ExerciceTemplate
{
Id = Guid.NewGuid().ToString(),
Name = "Running on Treadmill",

@ -8,9 +8,9 @@ public class MappingProfiles : Profile
{
public MappingProfiles()
{
CreateMap<Exercice, ExerciceTemplateDto>();
CreateMap<ExerciceTemplateDto, Exercice>();
CreateMap<CreateExerciceTemplateDto, Exercice>();
CreateMap<UpdateExerciceTemplateDto, Exercice>();
CreateMap<ExerciceTemplate, ExerciceTemplateDto>();
CreateMap<ExerciceTemplateDto, ExerciceTemplate>();
CreateMap<CreateExerciceTemplateDto, ExerciceTemplate>();
CreateMap<UpdateExerciceTemplateDto, ExerciceTemplate>();
}
}

@ -3,7 +3,7 @@ using Shared.Enum;
namespace CatalogService.Entities;
public class Exercice : EntityBase
public class ExerciceTemplate : EntityBase
{
public string Name { get; set; }

@ -0,0 +1,204 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using TrainingSvc.Data;
#nullable disable
namespace TrainingSvc.Data.Migrations
{
[DbContext(typeof(TrainingDbContext))]
[Migration("20250607133126_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.15")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("CatalogService.Entities.ExerciceTemplate", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ImageUrl")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Target")
.HasColumnType("integer");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("VideoUrl")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("ExerciceTemplates");
});
modelBuilder.Entity("TrainingSvc.Entities.ExerciceInstance", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<float>("Duration")
.HasColumnType("real");
b.Property<string>("ExerciceTemplateId")
.HasColumnType("text");
b.Property<bool>("IsDone")
.HasColumnType("boolean");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<int>("NbReps")
.HasColumnType("integer");
b.Property<int>("NbSets")
.HasColumnType("integer");
b.Property<float>("RestingTime")
.HasColumnType("real");
b.Property<string>("SessionId")
.IsRequired()
.HasColumnType("text");
b.Property<float?>("Weight")
.HasColumnType("real");
b.HasKey("Id");
b.HasIndex("SessionId");
b.ToTable("ExerciceInstances");
});
modelBuilder.Entity("TrainingSvc.Entities.Session", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("Day")
.HasColumnType("integer");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<int?>("Target")
.HasColumnType("integer");
b.Property<string>("TrainingProgramId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("TrainingProgramId");
b.ToTable("Sessions");
});
modelBuilder.Entity("TrainingSvc.Entities.TrainingProgram", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<int>("Difficulty")
.HasColumnType("integer");
b.Property<int>("Goal")
.HasColumnType("integer");
b.Property<string>("Lang")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<int>("NbDays")
.HasColumnType("integer");
b.Property<string>("OwnerId")
.IsRequired()
.HasColumnType("text");
b.Property<int>("WeekDuration")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("TrainingPrograms");
});
modelBuilder.Entity("TrainingSvc.Entities.ExerciceInstance", b =>
{
b.HasOne("TrainingSvc.Entities.Session", "Session")
.WithMany("Exercices")
.HasForeignKey("SessionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Session");
});
modelBuilder.Entity("TrainingSvc.Entities.Session", b =>
{
b.HasOne("TrainingSvc.Entities.TrainingProgram", "TrainingProgram")
.WithMany("Sessions")
.HasForeignKey("TrainingProgramId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("TrainingProgram");
});
modelBuilder.Entity("TrainingSvc.Entities.Session", b =>
{
b.Navigation("Exercices");
});
modelBuilder.Entity("TrainingSvc.Entities.TrainingProgram", b =>
{
b.Navigation("Sessions");
});
#pragma warning restore 612, 618
}
}
}

@ -0,0 +1,126 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace TrainingSvc.Data.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "ExerciceTemplates",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
Name = table.Column<string>(type: "text", nullable: false),
Description = table.Column<string>(type: "text", nullable: false),
Target = table.Column<int>(type: "integer", nullable: false),
ImageUrl = table.Column<string>(type: "text", nullable: false),
VideoUrl = table.Column<string>(type: "text", nullable: false),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ExerciceTemplates", x => x.Id);
});
migrationBuilder.CreateTable(
name: "TrainingPrograms",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
Lang = table.Column<string>(type: "text", nullable: false),
Name = table.Column<string>(type: "text", nullable: false),
Description = table.Column<string>(type: "text", nullable: true),
WeekDuration = table.Column<int>(type: "integer", nullable: false),
NbDays = table.Column<int>(type: "integer", nullable: false),
OwnerId = table.Column<string>(type: "text", nullable: false),
Goal = table.Column<int>(type: "integer", nullable: false),
Difficulty = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_TrainingPrograms", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Sessions",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
Name = table.Column<string>(type: "text", nullable: false),
Description = table.Column<string>(type: "text", nullable: true),
Day = table.Column<int>(type: "integer", nullable: false),
Target = table.Column<int>(type: "integer", nullable: true),
TrainingProgramId = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Sessions", x => x.Id);
table.ForeignKey(
name: "FK_Sessions_TrainingPrograms_TrainingProgramId",
column: x => x.TrainingProgramId,
principalTable: "TrainingPrograms",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ExerciceInstances",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
Name = table.Column<string>(type: "text", nullable: false),
ExerciceTemplateId = table.Column<string>(type: "text", nullable: true),
Duration = table.Column<float>(type: "real", nullable: false),
NbSets = table.Column<int>(type: "integer", nullable: false),
NbReps = table.Column<int>(type: "integer", nullable: false),
RestingTime = table.Column<float>(type: "real", nullable: false),
Weight = table.Column<float>(type: "real", nullable: true),
IsDone = table.Column<bool>(type: "boolean", nullable: false),
SessionId = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ExerciceInstances", x => x.Id);
table.ForeignKey(
name: "FK_ExerciceInstances_Sessions_SessionId",
column: x => x.SessionId,
principalTable: "Sessions",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_ExerciceInstances_SessionId",
table: "ExerciceInstances",
column: "SessionId");
migrationBuilder.CreateIndex(
name: "IX_Sessions_TrainingProgramId",
table: "Sessions",
column: "TrainingProgramId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "ExerciceInstances");
migrationBuilder.DropTable(
name: "ExerciceTemplates");
migrationBuilder.DropTable(
name: "Sessions");
migrationBuilder.DropTable(
name: "TrainingPrograms");
}
}
}

@ -0,0 +1,201 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using TrainingSvc.Data;
#nullable disable
namespace TrainingSvc.Data.Migrations
{
[DbContext(typeof(TrainingDbContext))]
partial class TrainingDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.15")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("CatalogService.Entities.ExerciceTemplate", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ImageUrl")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Target")
.HasColumnType("integer");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("VideoUrl")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("ExerciceTemplates");
});
modelBuilder.Entity("TrainingSvc.Entities.ExerciceInstance", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<float>("Duration")
.HasColumnType("real");
b.Property<string>("ExerciceTemplateId")
.HasColumnType("text");
b.Property<bool>("IsDone")
.HasColumnType("boolean");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<int>("NbReps")
.HasColumnType("integer");
b.Property<int>("NbSets")
.HasColumnType("integer");
b.Property<float>("RestingTime")
.HasColumnType("real");
b.Property<string>("SessionId")
.IsRequired()
.HasColumnType("text");
b.Property<float?>("Weight")
.HasColumnType("real");
b.HasKey("Id");
b.HasIndex("SessionId");
b.ToTable("ExerciceInstances");
});
modelBuilder.Entity("TrainingSvc.Entities.Session", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("Day")
.HasColumnType("integer");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<int?>("Target")
.HasColumnType("integer");
b.Property<string>("TrainingProgramId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("TrainingProgramId");
b.ToTable("Sessions");
});
modelBuilder.Entity("TrainingSvc.Entities.TrainingProgram", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<int>("Difficulty")
.HasColumnType("integer");
b.Property<int>("Goal")
.HasColumnType("integer");
b.Property<string>("Lang")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<int>("NbDays")
.HasColumnType("integer");
b.Property<string>("OwnerId")
.IsRequired()
.HasColumnType("text");
b.Property<int>("WeekDuration")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("TrainingPrograms");
});
modelBuilder.Entity("TrainingSvc.Entities.ExerciceInstance", b =>
{
b.HasOne("TrainingSvc.Entities.Session", "Session")
.WithMany("Exercices")
.HasForeignKey("SessionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Session");
});
modelBuilder.Entity("TrainingSvc.Entities.Session", b =>
{
b.HasOne("TrainingSvc.Entities.TrainingProgram", "TrainingProgram")
.WithMany("Sessions")
.HasForeignKey("TrainingProgramId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("TrainingProgram");
});
modelBuilder.Entity("TrainingSvc.Entities.Session", b =>
{
b.Navigation("Exercices");
});
modelBuilder.Entity("TrainingSvc.Entities.TrainingProgram", b =>
{
b.Navigation("Sessions");
});
#pragma warning restore 612, 618
}
}
}

@ -1,4 +1,6 @@
using CatalogService.Entities;
using Microsoft.EntityFrameworkCore;
using TrainingSvc.Entities;
namespace TrainingSvc.Data;
@ -8,4 +10,12 @@ public class TrainingDbContext : DbContext
{
}
public DbSet<ExerciceTemplate> ExerciceTemplates { get; set; }
public DbSet<ExerciceInstance> ExerciceInstances { get; set; }
public DbSet<Session> Sessions { get; set; }
public DbSet<TrainingProgram> TrainingPrograms { get; set; }
}

@ -0,0 +1,76 @@
namespace TrainingSvc.Data;
using CatalogService.Entities;
using Microsoft.EntityFrameworkCore;
using Shared.Enum;
public class TrainingDbInitializer
{
public static void InitDb(WebApplication app)
{
using var scope = app.Services.CreateScope();
SeedData(scope.ServiceProvider.GetService<TrainingDbContext>());
}
private static void SeedData(TrainingDbContext context)
{
context.Database.Migrate();
if (context.ExerciceTemplates.Any())
{
Console.WriteLine("Already have data in the database");
return;
}
var exercices = new List<ExerciceTemplate>()
{
new ExerciceTemplate
{
Id = Guid.NewGuid().ToString(),
Name = "Squat",
Description = "Squat is a compound exercise that targets the lower body, primarily the quadriceps, hamstrings, and glutes.",
Target = ETarget.Legs,
ImageUrl = "images/squat.jpg",
VideoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley",
},
new ExerciceTemplate
{
Id = Guid.NewGuid().ToString(),
Name = "Bench Press",
Description = "Bench Press is a compound exercise that primarily targets the chest, shoulders, and triceps.",
Target = ETarget.Chest,
ImageUrl = "images/bench_press.jpg",
VideoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley",
},
new ExerciceTemplate
{
Id = Guid.NewGuid().ToString(),
Name = "Deadlift",
Description = "Deadlift is a compound exercise that primarily targets the back, glutes, and hamstrings.",
Target = ETarget.Back,
ImageUrl = "images/deadlift.jpg",
VideoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley",
},
new ExerciceTemplate
{
Id = Guid.NewGuid().ToString(),
Name = "Shoulder Press",
Description = "Shoulder Press is a compound exercise that primarily targets the shoulders and triceps.",
Target = ETarget.Arms,
ImageUrl = "images/shoulder_press.jpg",
VideoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley",
},
new ExerciceTemplate
{
Id = Guid.NewGuid().ToString(),
Name = "Running on Treadmill",
Description = "Running on Treadmill is a cardiovascular exercise that primarily targets the legs and improves overall fitness.",
Target = ETarget.Cardio,
ImageUrl = "images/running_treadmill.jpg",
VideoUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley",
},
};
context.AddRange(exercices);
context.SaveChanges();
}
}

@ -7,7 +7,7 @@ public class ExerciceInstance : EntityBase
{
public required string Name { get; set; }
public string? ExerciceId { get; set; }
public string? ExerciceTemplateId { get; set; }
public float Duration { get; set; }

@ -21,13 +21,13 @@ app.MapControllers();
try
{
//NOT IMPLEMENTED
app.MapGet("/", () => "Hello World!");
//DbInitializer.InitDb(app);
TrainingDbInitializer.InitDb(app);
}
catch (Exception e)
{
Console.WriteLine(e);
}
app.Run();
app.Run();

@ -11,6 +11,10 @@
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.15" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.15">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.11" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>

Loading…
Cancel
Save