using Microsoft.EntityFrameworkCore; using EntityFrameworkCore.Domain; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using System.Reflection; using Microsoft.EntityFrameworkCore.Design; namespace EntityFrameworkCore.Data; public class DeadBallZoneLeagueDbContext : DbContext { public DeadBallZoneLeagueDbContext(DbContextOptions options) : base(options) { // This constuctor allows it to accept the options set from other instances, such as in the API project. } public DbSet Teams { get; set; } public DbSet Coaches { get; set; } public DbSet Leagues { get; set; } public DbSet Matches { get; set; } public DbSet TeamsAndLeaguesView { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { // modelBuilder.ApplyConfiguration(new TeamConfiguration()); // modelBuilder.ApplyConfiguration(new LeagueConfiguration()); // This line can be used, then individual configurations do not need to be loaded. modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); // This database object does not have a Primary Key, so we state that here, otherwise an exception is thrown. modelBuilder.Entity().HasNoKey().ToView("vw_TeamsAndLeagues"); // This is for user-defined functions. modelBuilder.HasDbFunction( typeof(DeadBallZoneLeagueDbContext) .GetMethod( nameof(GetEarliestTeamMatch), new[] {typeof(int)} )) .HasName("GetEarliestMatch"); } // This is an example override for SQL Server: // protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder.UseSqlServer("Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=FootballLeague_EfCore; Encrypt=true", sqlOptions => { // sqlOptions.EnableRetryOnFailure(maxRetryCount: 5, // maxRetryDelay: TimeSpan.FromSeconds(5), // errorNumbersToAdd: null); // }); protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) { // These apply to all the settings for all models. configurationBuilder.Properties().HaveMaxLength(100); configurationBuilder.Properties().HavePrecision(16, 2); } public override Task SaveChangesAsync(CancellationToken cancellationToken = default) { var entries = ChangeTracker.Entries().Where( λ => λ.State == EntityState.Modified || λ.State == EntityState.Added ); // Whenever a save is made to an entity, these fields are now automatically updated: foreach (var entry in entries) { entry.Entity.ModifiedDate = DateTime.UtcNow; entry.Entity.ModifiedBy = "Sample User 1"; if (entry.State == EntityState.Added) { entry.Entity.CreatedDate = DateTime.UtcNow; entry.Entity.CreatedBy = "Sample User"; } // Update the concurrency token. entry.Entity.Version = Guid.NewGuid(); } return base.SaveChangesAsync(cancellationToken); } public DateTime GetEarliestTeamMatch(int teamId) => throw new NotImplementedException(); } public class DeadBallZoneLeagueDbContextFactory : IDesignTimeDbContextFactory { public DeadBallZoneLeagueDbContext CreateDbContext(string[] args) { var folder = Environment.SpecialFolder.LocalApplicationData; var path = Environment.GetFolderPath(folder); IConfigurationRoot configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json") .Build(); var dbPath = Path.Combine(path, configuration.GetConnectionString("SqliteDatabaseName")); var optionsBuilder = new DbContextOptionsBuilder(); optionsBuilder.UseSqlite($"Data Source={dbPath}"); return new DeadBallZoneLeagueDbContext(optionsBuilder.Options); } }