using Microsoft.EntityFrameworkCore; using Microsoft.SelfService.Portal.Core.API.Extensions.Dataannotations; using Microsoft.SelfService.Portal.Core.API.Models; using System.Reflection; namespace Microsoft.SelfService.Portal.Core.API.Context { public class DataContext : DbContext { public DataContext(DbContextOptions options) : base(options) { } public DbSet Events { get; set; } public DbSet Environments { get; set; } public DbSet EnvironmentDomains { get; set; } public DbSet Domains { get; set; } public DbSet VirtualMachines { get; set; } public DbSet Deployments { get; set; } public DbSet DeploymentGroups { get; set; } public DbSet Templates { get; set; } public DbSet DeploymentRules { get; set; } public DbSet DeploymentRuleSteps { get; set; } public DbSet TemplateCategories { get; set; } public DbSet Services { get; set; } public DbSet ServiceRoleDefinitions { get; set; } public DbSet TemplateOptions { get; set; } public DbSet Options { get; set; } public DbSet OptionCategories { get; set; } public DbSet Jobs { get; set; } public DbSet Runbooks { get; set; } public DbSet QueueJobs { get; set; } public DbSet QueueJobTargets { get; set; } public DbSet QueueJobSteps { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity() .HasKey(ed => new { ed.EnvironmentId, ed.DomainId }); modelBuilder.Entity() .HasOne(ed => ed.Environment) .WithMany(e => e.EnvironmentDomains) .HasForeignKey(ed => ed.EnvironmentId); modelBuilder.Entity() .HasOne(ed => ed.Domain) .WithMany(d => d.EnvironmentDomains) .HasForeignKey(ed => ed.DomainId); modelBuilder.Entity() .HasKey(to => new { to.OptionId, to.TemplateId }); modelBuilder.Entity() .HasOne(to => to.Option) .WithMany(o => o.TemplateOptions) .HasForeignKey(to => to.OptionId); modelBuilder.Entity() .HasOne(to => to.Template) .WithMany(t => t.TemplateOptions) .HasForeignKey(to => to.TemplateId); modelBuilder.Entity() .HasOne(tc => tc.Service) .WithMany(s => s.TemplateCategories) .HasForeignKey(tc => tc.ServiceId); modelBuilder.Entity() .HasOne(role => role.Service) .WithMany(service => service.RoleDefinitions) .HasForeignKey(role => role.ServiceId); modelBuilder.Entity() .ToTable("DeploymentBatches"); modelBuilder.Entity() .ToTable("DeploymentExecutions"); modelBuilder.Entity() .Property(deployment => deployment.DeploymentGroupId) .HasColumnName("DeploymentBatchId"); modelBuilder.Entity() .ToTable("DeploymentJobs"); modelBuilder.Entity() .ToTable("DeploymentJobTargets"); modelBuilder.Entity() .Property(target => target.QueueJobId) .HasColumnName("DeploymentJobId"); modelBuilder.Entity() .Property(target => target.DeploymentGroupId) .HasColumnName("DeploymentBatchId"); modelBuilder.Entity() .ToTable("DeploymentJobSteps"); modelBuilder.Entity() .Property(step => step.QueueJobId) .HasColumnName("DeploymentJobId"); modelBuilder.Entity() .Property(step => step.DependsOnQueueJobStepId) .HasColumnName("DependsOnDeploymentJobStepId"); modelBuilder.Entity() .HasKey(d => new { d.VirtualMachineId, d.DeploymentGroupId }); modelBuilder.Entity() .HasOne(d => d.VirtualMachine) .WithMany(vm => vm.Deployments) .HasForeignKey(d => d.VirtualMachineId); modelBuilder.Entity() .HasOne(d => d.DeploymentGroup) .WithMany(dg => dg.Deployments) .HasForeignKey(d => d.DeploymentGroupId); modelBuilder.Entity() .HasOne(dg => dg.Template) .WithMany(t => t.DeploymentGroups) .HasForeignKey(dg => dg.TemplateId); modelBuilder.Entity() .HasOne(template => template.DeploymentRule) .WithMany() .HasForeignKey(template => template.DeploymentRuleId); modelBuilder.Entity() .HasOne(step => step.DeploymentRule) .WithMany(rule => rule.Steps) .HasForeignKey(step => step.DeploymentRuleId); modelBuilder.Entity() .HasOne(target => target.QueueJob) .WithMany(job => job.Targets) .HasForeignKey(target => target.QueueJobId); modelBuilder.Entity() .HasOne(step => step.QueueJob) .WithMany(job => job.Steps) .HasForeignKey(step => step.QueueJobId); modelBuilder.Entity() .HasOne(step => step.DependsOnQueueJobStep) .WithMany() .HasForeignKey(step => step.DependsOnQueueJobStepId) .OnDelete(DeleteBehavior.Restrict); modelBuilder.Entity() .HasKey(j => new { j.RunbookId, j.DeploymentId }); modelBuilder.Entity() .HasOne(j => j.Deployment) .WithMany(d => d.Jobs) .HasPrincipalKey(d => d.Id) .HasForeignKey(j => j.DeploymentId); modelBuilder.Entity() .HasOne(j => j.Runbook) .WithMany(r => r.Jobs) .HasPrincipalKey(r => r.Id) .HasForeignKey(j => j.RunbookId); modelBuilder.Entity() .HasOne(e => e.Runbook) .WithMany(r => r.Events) .HasPrincipalKey(e => e.Id) .HasForeignKey(r => r.RunbookId); OnModelCreatingAddDefaultSqlValues(modelBuilder); } private void OnModelCreatingAddDefaultSqlValues(ModelBuilder modelBuilder) { var assemblyName = "Microsoft.SelfService.Portal.Core.API"; var nameSpace = "Microsoft.SelfService.Portal.Core.API.Models"; var asm = Assembly.Load(assemblyName); List types = asm.GetTypes().Where(p => p.Namespace == nameSpace).ToList(); var dbSets = typeof(DataContext).GetProperties().Where(p => p.PropertyType.Name.ToLower().Contains("dbset")).ToList(); List dbSetTypes = new List(); foreach (PropertyInfo pi in dbSets) { dbSetTypes.Add(pi.PropertyType.GetGenericArguments()[0]); } foreach (Type t in types) { if (typeof(BaseModel).IsAssignableFrom(t) && t.Name != nameof(BaseModel) && dbSetTypes.Contains(t)) { var properties = t.GetProperties().ToList(); foreach (var p in properties) { var att = p.GetCustomAttribute(); if (att != null) { modelBuilder.Entity(t).Property(p.Name).HasDefaultValueSql(att.DefaultValueSql); } } } } } } }