mirror of
https://github.com/collinbarrett/FilterLists.git
synced 2026-03-11 09:04:27 +00:00
feat(dir): ✨ migrate QueryDbContext
This commit is contained in:
parent
d87473bfd6
commit
2dbbdd981e
21 changed files with 539 additions and 0 deletions
|
|
@ -0,0 +1,14 @@
|
|||
using FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
|
||||
|
||||
namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
|
||||
|
||||
public interface IQueryContext
|
||||
{
|
||||
IQueryable<FilterList> FilterLists { get; }
|
||||
IQueryable<Language> Languages { get; }
|
||||
IQueryable<License> Licenses { get; }
|
||||
IQueryable<Maintainer> Maintainers { get; }
|
||||
IQueryable<Software> Software { get; }
|
||||
IQueryable<Syntax> Syntaxes { get; }
|
||||
IQueryable<Tag> Tags { get; }
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
using FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
|
||||
|
||||
internal sealed class QueryContext(QueryDbContext dbContext) : IQueryContext, IAsyncDisposable, IDisposable
|
||||
{
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
return dbContext.DisposeAsync();
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
dbContext.Dispose();
|
||||
}
|
||||
|
||||
public IQueryable<FilterList> FilterLists => dbContext.FilterLists.AsNoTracking();
|
||||
public IQueryable<Language> Languages => dbContext.Languages.AsNoTracking();
|
||||
public IQueryable<License> Licenses => dbContext.Licenses.AsNoTracking();
|
||||
public IQueryable<Maintainer> Maintainers => dbContext.Maintainers.AsNoTracking();
|
||||
public IQueryable<Software> Software => dbContext.Software.AsNoTracking();
|
||||
public IQueryable<Syntax> Syntaxes => dbContext.Syntaxes.AsNoTracking();
|
||||
public IQueryable<Tag> Tags => dbContext.Tags.AsNoTracking();
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
using FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
|
||||
|
||||
public class QueryDbContext(DbContextOptions<QueryDbContext> options) : DbContext(options)
|
||||
{
|
||||
public DbSet<FilterList> FilterLists => Set<FilterList>();
|
||||
public DbSet<Language> Languages => Set<Language>();
|
||||
public DbSet<License> Licenses => Set<License>();
|
||||
public DbSet<Maintainer> Maintainers => Set<Maintainer>();
|
||||
public DbSet<Software> Software => Set<Software>();
|
||||
public DbSet<Syntax> Syntaxes => Set<Syntax>();
|
||||
public DbSet<Tag> Tags => Set<Tag>();
|
||||
|
||||
public override int SaveChanges(bool acceptAllChangesOnSuccess)
|
||||
{
|
||||
throw new InvalidOperationException("This context is read-only.");
|
||||
}
|
||||
|
||||
public override Task<int> SaveChangesAsync(
|
||||
bool acceptAllChangesOnSuccess,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new InvalidOperationException("This context is read-only.");
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.ApplyConfigurationsFromAssembly(
|
||||
GetType().Assembly,
|
||||
type => type.Namespace == typeof(FilterListTypeConfiguration).Namespace);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
|
||||
|
||||
public record Dependent
|
||||
{
|
||||
public long DependencyFilterListId { get; init; }
|
||||
public FilterList DependencyFilterList { get; init; } = default!;
|
||||
public long DependentFilterListId { get; init; }
|
||||
public FilterList DependentFilterList { get; init; } = default!;
|
||||
}
|
||||
|
||||
internal class DependentTypeConfiguration : IEntityTypeConfiguration<Dependent>
|
||||
{
|
||||
public virtual void Configure(EntityTypeBuilder<Dependent> builder)
|
||||
{
|
||||
builder.HasKey(d => new { d.DependencyFilterListId, d.DependentFilterListId });
|
||||
builder.HasOne(d => d.DependencyFilterList)
|
||||
.WithMany(fl => fl.DependentFilterLists)
|
||||
.HasForeignKey(d => d.DependencyFilterListId);
|
||||
builder.HasOne(d => d.DependentFilterList)
|
||||
.WithMany(fl => fl.DependencyFilterLists)
|
||||
.HasForeignKey(d => d.DependentFilterListId);
|
||||
builder.HasDataJsonFile<Dependent>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
|
||||
|
||||
public abstract record Entity
|
||||
{
|
||||
public long Id { get; init; }
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
|
||||
|
||||
public record FilterList : Entity
|
||||
{
|
||||
public string Name { get; init; } = default!;
|
||||
public string? Description { get; init; }
|
||||
public long LicenseId { get; init; }
|
||||
public License License { get; init; } = default!;
|
||||
public IEnumerable<FilterListSyntax> FilterListSyntaxes { get; init; } = new HashSet<FilterListSyntax>();
|
||||
public IEnumerable<FilterListLanguage> FilterListLanguages { get; init; } = new HashSet<FilterListLanguage>();
|
||||
public IEnumerable<FilterListTag> FilterListTags { get; init; } = new HashSet<FilterListTag>();
|
||||
public IEnumerable<FilterListViewUrl> ViewUrls { get; init; } = new HashSet<FilterListViewUrl>();
|
||||
public Uri? HomeUrl { get; init; }
|
||||
public Uri? OnionUrl { get; init; }
|
||||
public Uri? PolicyUrl { get; init; }
|
||||
public Uri? SubmissionUrl { get; init; }
|
||||
public Uri? IssuesUrl { get; init; }
|
||||
public Uri? ForumUrl { get; init; }
|
||||
public Uri? ChatUrl { get; init; }
|
||||
public string? EmailAddress { get; init; }
|
||||
public Uri? DonateUrl { get; init; }
|
||||
public IEnumerable<FilterListMaintainer> FilterListMaintainers { get; init; } = new HashSet<FilterListMaintainer>();
|
||||
public IEnumerable<Fork> UpstreamFilterLists { get; init; } = new HashSet<Fork>();
|
||||
public IEnumerable<Fork> ForkFilterLists { get; init; } = new HashSet<Fork>();
|
||||
public IEnumerable<Merge> IncludedInFilterLists { get; init; } = new HashSet<Merge>();
|
||||
public IEnumerable<Merge> IncludesFilterLists { get; init; } = new HashSet<Merge>();
|
||||
public IEnumerable<Dependent> DependencyFilterLists { get; init; } = new HashSet<Dependent>();
|
||||
public IEnumerable<Dependent> DependentFilterLists { get; init; } = new HashSet<Dependent>();
|
||||
}
|
||||
|
||||
internal class FilterListTypeConfiguration : IEntityTypeConfiguration<FilterList>
|
||||
{
|
||||
public virtual void Configure(EntityTypeBuilder<FilterList> builder)
|
||||
{
|
||||
builder.HasIndex(f => f.Name)
|
||||
.IsUnique();
|
||||
builder.Property(f => f.LicenseId)
|
||||
.HasDefaultValue(5);
|
||||
builder.HasOne(f => f.License)
|
||||
.WithMany(l => l.FilterLists)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
builder.OwnsMany(
|
||||
f => f.ViewUrls,
|
||||
b =>
|
||||
{
|
||||
b.Property(u => u.SegmentNumber)
|
||||
.HasDefaultValue(1);
|
||||
b.Property(u => u.Primariness)
|
||||
.HasDefaultValue(1);
|
||||
b.HasIndex(u => new { u.FilterListId, u.SegmentNumber, u.Primariness })
|
||||
.IsUnique();
|
||||
b.HasDataJsonFile<FilterListViewUrl>();
|
||||
});
|
||||
builder.HasDataJsonFile<FilterList>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
|
||||
|
||||
public record FilterListLanguage
|
||||
{
|
||||
public long FilterListId { get; init; }
|
||||
public FilterList FilterList { get; init; } = default!;
|
||||
public long LanguageId { get; init; }
|
||||
public Language Language { get; init; } = default!;
|
||||
}
|
||||
|
||||
internal class FilterListLanguageTypeConfiguration : IEntityTypeConfiguration<FilterListLanguage>
|
||||
{
|
||||
public virtual void Configure(EntityTypeBuilder<FilterListLanguage> builder)
|
||||
{
|
||||
builder.HasKey(fll => new { fll.FilterListId, fll.LanguageId });
|
||||
builder.HasDataJsonFile<FilterListLanguage>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
|
||||
|
||||
public record FilterListMaintainer
|
||||
{
|
||||
public long FilterListId { get; init; }
|
||||
public FilterList FilterList { get; init; } = default!;
|
||||
public long MaintainerId { get; init; }
|
||||
public Maintainer Maintainer { get; init; } = default!;
|
||||
}
|
||||
|
||||
internal class FilterListMaintainerTypeConfiguration : IEntityTypeConfiguration<FilterListMaintainer>
|
||||
{
|
||||
public virtual void Configure(EntityTypeBuilder<FilterListMaintainer> builder)
|
||||
{
|
||||
builder.HasKey(flm => new { flm.FilterListId, flm.MaintainerId });
|
||||
builder.HasDataJsonFile<FilterListMaintainer>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
|
||||
|
||||
public record FilterListSyntax
|
||||
{
|
||||
public long FilterListId { get; init; }
|
||||
public FilterList FilterList { get; init; } = default!;
|
||||
public long SyntaxId { get; init; }
|
||||
public Syntax Syntax { get; init; } = default!;
|
||||
}
|
||||
|
||||
internal class FilterListSyntaxTypeConfiguration : IEntityTypeConfiguration<FilterListSyntax>
|
||||
{
|
||||
public virtual void Configure(EntityTypeBuilder<FilterListSyntax> builder)
|
||||
{
|
||||
builder.HasKey(fls => new { fls.FilterListId, fls.SyntaxId });
|
||||
builder.HasDataJsonFile<FilterListSyntax>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
|
||||
|
||||
public record FilterListTag
|
||||
{
|
||||
public long FilterListId { get; init; }
|
||||
public FilterList FilterList { get; init; } = default!;
|
||||
public long TagId { get; init; }
|
||||
public Tag Tag { get; init; } = default!;
|
||||
}
|
||||
|
||||
internal class FilterListTagTypeConfiguration : IEntityTypeConfiguration<FilterListTag>
|
||||
{
|
||||
public virtual void Configure(EntityTypeBuilder<FilterListTag> builder)
|
||||
{
|
||||
builder.HasKey(flt => new { flt.FilterListId, flt.TagId });
|
||||
builder.HasDataJsonFile<FilterListTag>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
|
||||
|
||||
public record FilterListViewUrl : Entity
|
||||
{
|
||||
public long FilterListId { get; init; }
|
||||
public FilterList FilterList { get; init; } = default!;
|
||||
public short SegmentNumber { get; init; }
|
||||
public short Primariness { get; init; }
|
||||
public Uri Url { get; init; } = default!;
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
|
||||
|
||||
public record Fork
|
||||
{
|
||||
public long UpstreamFilterListId { get; init; }
|
||||
public FilterList UpstreamFilterList { get; init; } = default!;
|
||||
public long ForkFilterListId { get; init; }
|
||||
public FilterList ForkFilterList { get; init; } = default!;
|
||||
}
|
||||
|
||||
internal class ForkTypeConfiguration : IEntityTypeConfiguration<Fork>
|
||||
{
|
||||
public virtual void Configure(EntityTypeBuilder<Fork> builder)
|
||||
{
|
||||
builder.HasKey(f => new { f.UpstreamFilterListId, f.ForkFilterListId });
|
||||
builder.HasOne(f => f.UpstreamFilterList)
|
||||
.WithMany(fl => fl.ForkFilterLists)
|
||||
.HasForeignKey(f => f.UpstreamFilterListId);
|
||||
builder.HasOne(f => f.ForkFilterList)
|
||||
.WithMany(fl => fl.UpstreamFilterLists)
|
||||
.HasForeignKey(f => f.ForkFilterListId);
|
||||
builder.HasDataJsonFile<Fork>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
|
||||
|
||||
public record Language : Entity
|
||||
{
|
||||
public string Iso6391 { get; init; } = default!;
|
||||
public string Name { get; init; } = default!;
|
||||
public IEnumerable<FilterListLanguage> FilterListLanguages { get; init; } = new HashSet<FilterListLanguage>();
|
||||
}
|
||||
|
||||
internal class LanguageTypeConfiguration : IEntityTypeConfiguration<Language>
|
||||
{
|
||||
public virtual void Configure(EntityTypeBuilder<Language> builder)
|
||||
{
|
||||
builder.Property(l => l.Iso6391)
|
||||
.IsFixedLength()
|
||||
.HasMaxLength(2);
|
||||
builder.HasIndex(l => l.Iso6391)
|
||||
.IsUnique();
|
||||
builder.HasIndex(l => l.Name)
|
||||
.IsUnique();
|
||||
builder.HasDataJsonFile<Language>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
|
||||
|
||||
public record License : Entity
|
||||
{
|
||||
public string Name { get; init; } = default!;
|
||||
public Uri? Url { get; init; }
|
||||
public bool PermitsModification { get; init; }
|
||||
public bool PermitsDistribution { get; init; }
|
||||
public bool PermitsCommercialUse { get; init; }
|
||||
public IEnumerable<FilterList> FilterLists { get; init; } = new HashSet<FilterList>();
|
||||
}
|
||||
|
||||
internal class LicenseTypeConfiguration : IEntityTypeConfiguration<License>
|
||||
{
|
||||
public virtual void Configure(EntityTypeBuilder<License> builder)
|
||||
{
|
||||
builder.HasIndex(l => l.Name)
|
||||
.IsUnique();
|
||||
builder.Property(l => l.PermitsModification)
|
||||
.HasDefaultValue(false);
|
||||
builder.Property(l => l.PermitsDistribution)
|
||||
.HasDefaultValue(false);
|
||||
builder.Property(l => l.PermitsCommercialUse)
|
||||
.HasDefaultValue(false);
|
||||
builder.HasDataJsonFile<License>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
|
||||
|
||||
public record Maintainer : Entity
|
||||
{
|
||||
public string Name { get; init; } = default!;
|
||||
public Uri? Url { get; init; }
|
||||
public string? EmailAddress { get; init; }
|
||||
public string? TwitterHandle { get; init; }
|
||||
public IEnumerable<FilterListMaintainer> FilterListMaintainers { get; init; } = new HashSet<FilterListMaintainer>();
|
||||
}
|
||||
|
||||
internal class MaintainerTypeConfiguration : IEntityTypeConfiguration<Maintainer>
|
||||
{
|
||||
public virtual void Configure(EntityTypeBuilder<Maintainer> builder)
|
||||
{
|
||||
builder.HasIndex(m => m.Name)
|
||||
.IsUnique();
|
||||
builder.HasDataJsonFile<Maintainer>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
|
||||
|
||||
public record Merge
|
||||
{
|
||||
public long IncludedInFilterListId { get; init; }
|
||||
public FilterList IncludedInFilterList { get; init; } = default!;
|
||||
public long IncludesFilterListId { get; init; }
|
||||
public FilterList IncludesFilterList { get; init; } = default!;
|
||||
}
|
||||
|
||||
internal class MergeTypeConfiguration : IEntityTypeConfiguration<Merge>
|
||||
{
|
||||
public virtual void Configure(EntityTypeBuilder<Merge> builder)
|
||||
{
|
||||
builder.HasKey(m => new { m.IncludedInFilterListId, m.IncludesFilterListId });
|
||||
builder.HasOne(m => m.IncludedInFilterList)
|
||||
.WithMany(fl => fl.IncludesFilterLists)
|
||||
.HasForeignKey(m => m.IncludedInFilterListId);
|
||||
builder.HasOne(m => m.IncludesFilterList)
|
||||
.WithMany(fl => fl.IncludedInFilterLists)
|
||||
.HasForeignKey(m => m.IncludesFilterListId);
|
||||
builder.HasDataJsonFile<Merge>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
|
||||
|
||||
public record Software : Entity
|
||||
{
|
||||
public string Name { get; init; } = default!;
|
||||
public string? Description { get; init; }
|
||||
public Uri? HomeUrl { get; init; }
|
||||
public Uri? DownloadUrl { get; init; }
|
||||
public bool SupportsAbpUrlScheme { get; init; }
|
||||
public IEnumerable<SoftwareSyntax> SoftwareSyntaxes { get; init; } = new HashSet<SoftwareSyntax>();
|
||||
}
|
||||
|
||||
internal class SoftwareTypeConfiguration : IEntityTypeConfiguration<Software>
|
||||
{
|
||||
public virtual void Configure(EntityTypeBuilder<Software> builder)
|
||||
{
|
||||
builder.HasIndex(s => s.Name)
|
||||
.IsUnique();
|
||||
builder.Property(s => s.SupportsAbpUrlScheme)
|
||||
.HasDefaultValue(false);
|
||||
builder.HasDataJsonFile<Software>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
|
||||
|
||||
public record SoftwareSyntax
|
||||
{
|
||||
public long SoftwareId { get; init; }
|
||||
public Software Software { get; init; } = default!;
|
||||
public long SyntaxId { get; init; }
|
||||
public Syntax Syntax { get; init; } = default!;
|
||||
}
|
||||
|
||||
internal class SoftwareSyntaxTypeConfiguration : IEntityTypeConfiguration<SoftwareSyntax>
|
||||
{
|
||||
public virtual void Configure(EntityTypeBuilder<SoftwareSyntax> builder)
|
||||
{
|
||||
builder.HasKey(ss => new { ss.SoftwareId, ss.SyntaxId });
|
||||
builder.HasDataJsonFile<SoftwareSyntax>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
|
||||
|
||||
public record Syntax : Entity
|
||||
{
|
||||
public string Name { get; init; } = default!;
|
||||
public string? Description { get; init; }
|
||||
public Uri? Url { get; init; }
|
||||
public IEnumerable<FilterListSyntax> FilterListSyntaxes { get; init; } = new HashSet<FilterListSyntax>();
|
||||
public IEnumerable<SoftwareSyntax> SoftwareSyntaxes { get; init; } = new HashSet<SoftwareSyntax>();
|
||||
}
|
||||
|
||||
internal class SyntaxTypeConfiguration : IEntityTypeConfiguration<Syntax>
|
||||
{
|
||||
public virtual void Configure(EntityTypeBuilder<Syntax> builder)
|
||||
{
|
||||
builder.HasIndex(s => s.Name)
|
||||
.IsUnique();
|
||||
builder.HasDataJsonFile<Syntax>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities;
|
||||
|
||||
public record Tag : Entity
|
||||
{
|
||||
public string Name { get; init; } = default!;
|
||||
public string? Description { get; init; }
|
||||
public IEnumerable<FilterListTag> FilterListTags { get; init; } = new HashSet<FilterListTag>();
|
||||
}
|
||||
|
||||
internal class TagTypeConfiguration : IEntityTypeConfiguration<Tag>
|
||||
{
|
||||
public virtual void Configure(EntityTypeBuilder<Tag> builder)
|
||||
{
|
||||
builder.HasIndex(t => t.Name)
|
||||
.IsUnique();
|
||||
builder.HasDataJsonFile<Tag>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
using System.Text.Json;
|
||||
using FilterLists.Directory.Infrastructure.Persistence.Queries.Context;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace FilterLists.Directory.Infrastructure.Persistence;
|
||||
|
||||
public static class SeedExtension
|
||||
{
|
||||
public static async Task MigrateAsync(this IHost host)
|
||||
{
|
||||
using var scope = host.Services.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<QueryDbContext>();
|
||||
await db.Database.MigrateAsync();
|
||||
}
|
||||
}
|
||||
|
||||
internal static class SeedConfigurationExtensions
|
||||
{
|
||||
private static readonly JsonSerializerOptions CamelCaseJsonSerializerOptions =
|
||||
new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
|
||||
|
||||
public static void HasDataJsonFile<TEntity>(this EntityTypeBuilder entityTypeBuilder) where TEntity : class
|
||||
{
|
||||
var entities = Deserialize<TEntity>();
|
||||
if (entities.Count == 0) return;
|
||||
|
||||
entityTypeBuilder.HasData(entities);
|
||||
}
|
||||
|
||||
public static void HasDataJsonFile<TEntity>(this OwnedNavigationBuilder ownedNavigationBuilder)
|
||||
where TEntity : class
|
||||
{
|
||||
var entities = Deserialize<TEntity>();
|
||||
if (entities.Count == 0) return;
|
||||
|
||||
ownedNavigationBuilder.HasData(entities);
|
||||
}
|
||||
|
||||
private static List<TEntity> Deserialize<TEntity>()
|
||||
{
|
||||
// uncomment to short-circuit HasData() when adding a migration
|
||||
//return new List<TEntity>();
|
||||
|
||||
var path = Path.Combine("../data", $"{typeof(TEntity).Name}.json");
|
||||
if (!File.Exists(path)) return [];
|
||||
|
||||
var entitiesJson = File.ReadAllText(path);
|
||||
var entities = JsonSerializer.Deserialize<IEnumerable<TEntity>>(
|
||||
entitiesJson,
|
||||
CamelCaseJsonSerializerOptions);
|
||||
return entities is null ? [] : entities.ToList();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue