using System; using System.IO; using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; using Microsoft.Extensions.Configuration; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; namespace Selector.Model { public class ApplicationDbContext : IdentityDbContext { private readonly ILogger Logger; public DbSet Watcher { get; set; } public DbSet Scrobble { get; set; } public DbSet TrackMapping { get; set; } public DbSet AlbumMapping { get; set; } public DbSet ArtistMapping { get; set; } public ApplicationDbContext( DbContextOptions options, ILogger logger ) : base(options) { Logger = logger; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.HasCollation("case_insensitive", locale: "en-u-ks-primary", provider: "icu", deterministic: false); modelBuilder.Entity() .Property(u => u.SpotifyIsLinked) .IsRequired(); modelBuilder.Entity() .Property(u => u.LastFmUsername) .UseCollation("case_insensitive"); modelBuilder.Entity() .HasOne(w => w.User) .WithMany(u => u.Watchers) .HasForeignKey(w => w.UserId); modelBuilder.Entity().HasKey(s => new { s.UserId, s.Timestamp }); modelBuilder.Entity() .HasOne(w => w.User) .WithMany(u => u.Scrobbles) .HasForeignKey(w => w.UserId); modelBuilder.Entity() .Property(s => s.TrackName) .UseCollation("case_insensitive"); modelBuilder.Entity() .Property(s => s.AlbumName) .UseCollation("case_insensitive"); modelBuilder.Entity() .Property(s => s.ArtistName) .UseCollation("case_insensitive"); modelBuilder.Entity().HasKey(s => s.Id); modelBuilder.Entity() .Property(s => s.LastfmTrackName) .UseCollation("case_insensitive"); modelBuilder.Entity() .Property(s => s.LastfmArtistName) .UseCollation("case_insensitive"); modelBuilder.Entity().HasKey(s => s.Id); modelBuilder.Entity() .Property(s => s.LastfmAlbumName) .UseCollation("case_insensitive"); modelBuilder.Entity() .Property(s => s.LastfmArtistName) .UseCollation("case_insensitive"); modelBuilder.Entity().HasKey(s => s.Id); modelBuilder.Entity() .Property(s => s.LastfmArtistName) .UseCollation("case_insensitive"); SeedData.Seed(modelBuilder); } public void CreatePlayerWatcher(string userId) { if(Watcher.Any(w => w.UserId == userId && w.Type == WatcherType.Player)) { Logger.LogWarning($"Trying to create more than one player watcher for user [{userId}]"); return; } Watcher.Add(new Watcher { UserId = userId, Type = WatcherType.Player }); SaveChanges(); } } public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory { private static string GetPath(string env) => $"{@Directory.GetCurrentDirectory()}/../Selector.Web/appsettings.{env}.json"; public ApplicationDbContext CreateDbContext(string[] args) { string configFile; if(File.Exists(GetPath("Development"))) { configFile = GetPath("Development"); } else if(File.Exists(GetPath("Production"))) { configFile = GetPath("Production"); } else { throw new FileNotFoundException("No config file available to load a connection string from"); } IConfigurationRoot configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile(configFile) .Build(); var builder = new DbContextOptionsBuilder(); builder.UseNpgsql(configuration.GetConnectionString("Default")); return new ApplicationDbContext(builder.Options, NullLogger.Instance); } } }