WIP: Add EF Core packages and create DbContext with entity configurations #68

Closed
Copilot wants to merge 3 commits from copilot/add-ef-core-packages into main
Copilot commented 2026-01-19 09:58:47 +00:00 (Migrated from github.com)

Implements foundational Entity Framework Core infrastructure for migrating from ADO.NET to EF Core. Part of the EF Core migration epic (#58).

Packages Added

Six EF Core 9.0.0 packages to support multiple database providers:

  • Core: Microsoft.EntityFrameworkCore, Microsoft.EntityFrameworkCore.Design
  • Providers: SQLite, PostgreSQL (Npgsql), SQL Server, MySQL (Pomelo)

Entity Models

Created 5 entity classes in Data/Entities/ mapping to existing SQLite schema:

  • Feed - feed configuration with YouTube settings
  • Episode - episode metadata with fuzzy match scores
  • DownloadedVideo - download tracking with composite unique constraint
  • ActivityLog - activity monitoring with optional feed reference
  • DownloadQueueItem - download queue state

All entities include navigation properties for EF relationships.

Entity Configurations

Fluent API configurations in Data/Configurations/ preserve existing schema:

  • Snake_case column naming matches current SQLite tables
  • Composite indexes on (feed_id, filename), (feed_id, display_order), (feed_id, video_id)
  • Unique constraints on Feed.Name and (FeedId, VideoId) for downloads
  • Cascade deletes from Feed to dependent entities

Example configuration:

builder.Property(e => e.Filename)
    .HasColumnName("filename")
    .IsRequired()
    .HasMaxLength(500);

builder.HasIndex(e => new { e.FeedId, e.Filename })
    .HasDatabaseName("idx_episodes_filename");

DbContext Registration

Registered CastrDbContext in DI container with temporary SQLite configuration using same path as existing CentralDatabaseService:

builder.Services.AddDbContext<CastrDbContext>(options =>
    options.UseSqlite($"Data Source={centralDbPath}"));

Enables side-by-side operation during migration without schema conflicts.

Testing

Added 9 tests covering entity CRUD, relationships, constraints, and cascade deletes. All tests use in-memory SQLite databases for isolation.

Original prompt

This section details on the original issue you should resolve

<issue_title>Add EF Core packages and create DbContext</issue_title>
<issue_description>## Parent Epic
Part of joezombie/btb_pod#58 - Migrate to Entity Framework Core

Description

Add Entity Framework Core NuGet packages and create the initial CastrDbContext class.

Packages to Add

<!-- Core EF packages -->
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0" />

<!-- Database providers -->
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0" />

DbContext Implementation

Create Data/CastrDbContext.cs:

public class CastrDbContext : DbContext
{
    public CastrDbContext(DbContextOptions<CastrDbContext> options) 
        : base(options) { }

    public DbSet<Feed> Feeds => Set<Feed>();
    public DbSet<Episode> Episodes => Set<Episode>();
    public DbSet<DownloadedVideo> DownloadedVideos => Set<DownloadedVideo>();
    public DbSet<ActivityLog> ActivityLogs => Set<ActivityLog>();
    public DbSet<DownloadQueueItem> DownloadQueue => Set<DownloadQueueItem>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // Configure relationships, indexes, constraints
        modelBuilder.ApplyConfigurationsFromAssembly(typeof(CastrDbContext).Assembly);
    }
}

File Structure

Castr/
├── Data/
│   ├── CastrDbContext.cs
│   ├── Configurations/
│   │   ├── FeedConfiguration.cs
│   │   ├── EpisodeConfiguration.cs
│   │   ├── DownloadedVideoConfiguration.cs
│   │   ├── ActivityLogConfiguration.cs
│   │   └── DownloadQueueItemConfiguration.cs
│   └── Migrations/
│       └── (EF Core generated migrations)

Tasks

  • Add EF Core packages to Castr.csproj
  • Create Data folder structure
  • Implement CastrDbContext with DbSets
  • Add basic OnModelCreating configuration
  • Register DbContext in Program.cs (temporary SQLite config)
  • Verify project builds successfully

Acceptance Criteria

  • All packages install without conflicts
  • DbContext compiles and can be instantiated
  • EF Core tools work (dotnet ef commands)</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Implements foundational Entity Framework Core infrastructure for migrating from ADO.NET to EF Core. Part of the EF Core migration epic (#58). ## Packages Added Six EF Core 9.0.0 packages to support multiple database providers: - Core: `Microsoft.EntityFrameworkCore`, `Microsoft.EntityFrameworkCore.Design` - Providers: SQLite, PostgreSQL (Npgsql), SQL Server, MySQL (Pomelo) ## Entity Models Created 5 entity classes in `Data/Entities/` mapping to existing SQLite schema: - `Feed` - feed configuration with YouTube settings - `Episode` - episode metadata with fuzzy match scores - `DownloadedVideo` - download tracking with composite unique constraint - `ActivityLog` - activity monitoring with optional feed reference - `DownloadQueueItem` - download queue state All entities include navigation properties for EF relationships. ## Entity Configurations Fluent API configurations in `Data/Configurations/` preserve existing schema: - Snake_case column naming matches current SQLite tables - Composite indexes on `(feed_id, filename)`, `(feed_id, display_order)`, `(feed_id, video_id)` - Unique constraints on `Feed.Name` and `(FeedId, VideoId)` for downloads - Cascade deletes from Feed to dependent entities Example configuration: ```csharp builder.Property(e => e.Filename) .HasColumnName("filename") .IsRequired() .HasMaxLength(500); builder.HasIndex(e => new { e.FeedId, e.Filename }) .HasDatabaseName("idx_episodes_filename"); ``` ## DbContext Registration Registered `CastrDbContext` in DI container with temporary SQLite configuration using same path as existing `CentralDatabaseService`: ```csharp builder.Services.AddDbContext<CastrDbContext>(options => options.UseSqlite($"Data Source={centralDbPath}")); ``` Enables side-by-side operation during migration without schema conflicts. ## Testing Added 9 tests covering entity CRUD, relationships, constraints, and cascade deletes. All tests use in-memory SQLite databases for isolation. <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> > > ---- > > *This section details on the original issue you should resolve* > > <issue_title>Add EF Core packages and create DbContext</issue_title> > <issue_description>## Parent Epic > Part of joezombie/btb_pod#58 - Migrate to Entity Framework Core > > ## Description > Add Entity Framework Core NuGet packages and create the initial `CastrDbContext` class. > > ## Packages to Add > > ```xml > <!-- Core EF packages --> > <PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" /> > <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0" /> > > <!-- Database providers --> > <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.0" /> > <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.0" /> > <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" /> > <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0" /> > ``` > > ## DbContext Implementation > > Create `Data/CastrDbContext.cs`: > > ```csharp > public class CastrDbContext : DbContext > { > public CastrDbContext(DbContextOptions<CastrDbContext> options) > : base(options) { } > > public DbSet<Feed> Feeds => Set<Feed>(); > public DbSet<Episode> Episodes => Set<Episode>(); > public DbSet<DownloadedVideo> DownloadedVideos => Set<DownloadedVideo>(); > public DbSet<ActivityLog> ActivityLogs => Set<ActivityLog>(); > public DbSet<DownloadQueueItem> DownloadQueue => Set<DownloadQueueItem>(); > > protected override void OnModelCreating(ModelBuilder modelBuilder) > { > // Configure relationships, indexes, constraints > modelBuilder.ApplyConfigurationsFromAssembly(typeof(CastrDbContext).Assembly); > } > } > ``` > > ## File Structure > > ``` > Castr/ > ├── Data/ > │ ├── CastrDbContext.cs > │ ├── Configurations/ > │ │ ├── FeedConfiguration.cs > │ │ ├── EpisodeConfiguration.cs > │ │ ├── DownloadedVideoConfiguration.cs > │ │ ├── ActivityLogConfiguration.cs > │ │ └── DownloadQueueItemConfiguration.cs > │ └── Migrations/ > │ └── (EF Core generated migrations) > ``` > > ## Tasks > - [ ] Add EF Core packages to Castr.csproj > - [ ] Create Data folder structure > - [ ] Implement CastrDbContext with DbSets > - [ ] Add basic OnModelCreating configuration > - [ ] Register DbContext in Program.cs (temporary SQLite config) > - [ ] Verify project builds successfully > > ## Acceptance Criteria > - [ ] All packages install without conflicts > - [ ] DbContext compiles and can be instantiated > - [ ] EF Core tools work (`dotnet ef` commands)</issue_description> > > ## Comments on the Issue (you are @copilot in this section) > > <comments> > </comments> > </details> <!-- START COPILOT CODING AGENT SUFFIX --> - Fixes joezombie/btb_pod#59 <!-- START COPILOT CODING AGENT TIPS --> --- ✨ Let Copilot coding agent [set things up for you](https://github.com/joezombie/btb_pod/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo.
joezombie (Migrated from github.com) reviewed 2026-01-19 09:58:47 +00:00

Pull request closed

Sign in to join this conversation.
No description provided.