183 lines
7.4 KiB
C#
183 lines
7.4 KiB
C#
using MetaCourse.Api.Entities;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace MetaCourse.Api.Data;
|
|
|
|
public class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
|
|
{
|
|
|
|
public DbSet<User> Users => Set<User>();
|
|
public DbSet<Course> Courses => Set<Course>();
|
|
public DbSet<Topic> Topics => Set<Topic>();
|
|
public DbSet<Resource> Resources => Set<Resource>();
|
|
public DbSet<TopicResource> TopicResources => Set<TopicResource>();
|
|
public DbSet<UserCourse> UserCourses => Set<UserCourse>();
|
|
public DbSet<UserTopicProgress> UserTopicProgresses => Set<UserTopicProgress>();
|
|
public DbSet<UserResourceProgress> UserResourceProgresses => Set<UserResourceProgress>();
|
|
|
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
|
{
|
|
// TopicResource composite key
|
|
modelBuilder.Entity<TopicResource>()
|
|
.HasKey(tr => new { tr.TopicId, tr.ResourceId });
|
|
|
|
modelBuilder.Entity<TopicResource>()
|
|
.HasOne(tr => tr.Topic)
|
|
.WithMany(t => t.TopicResources)
|
|
.HasForeignKey(tr => tr.TopicId);
|
|
|
|
modelBuilder.Entity<TopicResource>()
|
|
.HasOne(tr => tr.Resource)
|
|
.WithMany(r => r.TopicResources)
|
|
.HasForeignKey(tr => tr.ResourceId);
|
|
|
|
// UserCourse composite key
|
|
modelBuilder.Entity<UserCourse>()
|
|
.HasKey(uc => new { uc.UserId, uc.CourseId });
|
|
|
|
modelBuilder.Entity<UserCourse>()
|
|
.HasOne(uc => uc.User)
|
|
.WithMany(u => u.UserCourses)
|
|
.HasForeignKey(uc => uc.UserId);
|
|
|
|
modelBuilder.Entity<UserCourse>()
|
|
.HasOne(uc => uc.Course)
|
|
.WithMany(c => c.UserCourses)
|
|
.HasForeignKey(uc => uc.CourseId);
|
|
|
|
// UserTopicProgress composite key
|
|
modelBuilder.Entity<UserTopicProgress>()
|
|
.HasKey(utp => new { utp.UserId, utp.TopicId });
|
|
|
|
modelBuilder.Entity<UserTopicProgress>()
|
|
.HasOne(utp => utp.User)
|
|
.WithMany(u => u.TopicProgresses)
|
|
.HasForeignKey(utp => utp.UserId);
|
|
|
|
modelBuilder.Entity<UserTopicProgress>()
|
|
.HasOne(utp => utp.Topic)
|
|
.WithMany(t => t.UserProgresses)
|
|
.HasForeignKey(utp => utp.TopicId);
|
|
|
|
// UserResourceProgress composite key
|
|
modelBuilder.Entity<UserResourceProgress>()
|
|
.HasKey(urp => new { urp.UserId, urp.ResourceId });
|
|
|
|
modelBuilder.Entity<UserResourceProgress>()
|
|
.HasOne(urp => urp.User)
|
|
.WithMany(u => u.ResourceProgresses)
|
|
.HasForeignKey(urp => urp.UserId);
|
|
|
|
modelBuilder.Entity<UserResourceProgress>()
|
|
.HasOne(urp => urp.Resource)
|
|
.WithMany(r => r.UserProgresses)
|
|
.HasForeignKey(urp => urp.ResourceId);
|
|
|
|
// Unique email
|
|
modelBuilder.Entity<User>()
|
|
.HasIndex(u => u.Email)
|
|
.IsUnique();
|
|
|
|
// Course -> Creator (restrict delete to avoid cascade)
|
|
modelBuilder.Entity<Course>()
|
|
.HasOne(c => c.Creator)
|
|
.WithMany(u => u.CreatedCourses)
|
|
.HasForeignKey(c => c.CreatorId)
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
|
|
// Enum stored as string
|
|
modelBuilder.Entity<Course>()
|
|
.Property(c => c.Status)
|
|
.HasConversion<string>();
|
|
|
|
modelBuilder.Entity<Resource>()
|
|
.Property(r => r.Type)
|
|
.HasConversion<string>();
|
|
|
|
SeedData(modelBuilder);
|
|
}
|
|
|
|
private static void SeedData(ModelBuilder modelBuilder)
|
|
{
|
|
var userId1 = Guid.Parse("11111111-1111-1111-1111-111111111111");
|
|
var userId2 = Guid.Parse("22222222-2222-2222-2222-222222222222");
|
|
|
|
var courseId1 = Guid.Parse("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa");
|
|
var courseId2 = Guid.Parse("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb");
|
|
|
|
var topicId1 = Guid.Parse("cccccccc-cccc-cccc-cccc-cccccccccccc");
|
|
var topicId2 = Guid.Parse("dddddddd-dddd-dddd-dddd-dddddddddddd");
|
|
var topicId3 = Guid.Parse("eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee");
|
|
|
|
var resourceId1 = Guid.Parse("ffffffff-ffff-ffff-ffff-ffffffffffff");
|
|
var resourceId2 = Guid.Parse("00000000-0000-0000-aaaa-000000000001");
|
|
var resourceId3 = Guid.Parse("00000000-0000-0000-aaaa-000000000002");
|
|
|
|
var now = new DateTime(2025, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
|
|
|
modelBuilder.Entity<User>().HasData(
|
|
new User
|
|
{
|
|
Id = userId1,
|
|
Name = "Alice Dupont",
|
|
Email = "alice@metacourse.io",
|
|
PasswordHash = "$2a$11$EuQ5pngrcHnxS6BhcMo6Mut73tAaJSDYB7K9TxahwJa5wAnJCF2o6",
|
|
CreatedAt = now
|
|
},
|
|
new User
|
|
{
|
|
Id = userId2,
|
|
Name = "Bob Martin",
|
|
Email = "bob@metacourse.io",
|
|
PasswordHash = "$2a$11$4.r72zZul8Pj.QJ5kmVNE.0dRJuAmIefGvZtt9xZ1.fAzztjGKqtS",
|
|
CreatedAt = now
|
|
}
|
|
);
|
|
|
|
modelBuilder.Entity<Course>().HasData(
|
|
new Course
|
|
{
|
|
Id = courseId1,
|
|
Title = "Développement Web Moderne avec React",
|
|
Description = "Maîtrisez React, Tailwind CSS et TypeScript pour créer des applications web performantes.",
|
|
Status = CourseStatus.Published,
|
|
CreatorId = userId1,
|
|
CreatedAt = now,
|
|
UpdatedAt = now
|
|
},
|
|
new Course
|
|
{
|
|
Id = courseId2,
|
|
Title = "API REST avec .NET et FastEndpoints",
|
|
Description = "Apprenez à construire des APIs REST robustes avec ASP.NET Core et FastEndpoints.",
|
|
Status = CourseStatus.Draft,
|
|
CreatorId = userId2,
|
|
CreatedAt = now,
|
|
UpdatedAt = now
|
|
}
|
|
);
|
|
|
|
modelBuilder.Entity<Topic>().HasData(
|
|
new Topic { Id = topicId1, Title = "Introduction à React", Description = "Les bases de React : composants, JSX, props.", Position = 1, CourseId = courseId1 },
|
|
new Topic { Id = topicId2, Title = "Hooks et State", Description = "useState, useEffect et hooks personnalisés.", Position = 2, CourseId = courseId1 },
|
|
new Topic { Id = topicId3, Title = "Fondamentaux REST", Description = "Principes REST et verbes HTTP.", Position = 1, CourseId = courseId2 }
|
|
);
|
|
|
|
modelBuilder.Entity<Resource>().HasData(
|
|
new Resource { Id = resourceId1, Type = ResourceType.Video, Title = "React en 30 minutes", Content = "https://youtube.com/watch?v=example1", CreatedAt = now },
|
|
new Resource { Id = resourceId2, Type = ResourceType.Text, Title = "Guide des Hooks", Content = "Les hooks permettent d'utiliser le state et d'autres fonctionnalités React dans des composants fonctionnels.", CreatedAt = now },
|
|
new Resource { Id = resourceId3, Type = ResourceType.Url, Title = "Documentation officielle React", Content = "https://react.dev", CreatedAt = now }
|
|
);
|
|
|
|
modelBuilder.Entity<TopicResource>().HasData(
|
|
new TopicResource { TopicId = topicId1, ResourceId = resourceId1, Position = 1 },
|
|
new TopicResource { TopicId = topicId1, ResourceId = resourceId3, Position = 2 },
|
|
new TopicResource { TopicId = topicId2, ResourceId = resourceId2, Position = 1 }
|
|
);
|
|
|
|
modelBuilder.Entity<UserCourse>().HasData(
|
|
new UserCourse { UserId = userId2, CourseId = courseId1, EnrolledAt = now }
|
|
);
|
|
}
|
|
}
|