using System.Globalization; using System.Linq.Expressions; using System.Reflection; using AutoMapPropertyHelper; using EntityFrameworkCore.Projectables; using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.EntityFrameworkCore; namespace NejCommon.Models; public abstract class CommonDbContext : DbContext { public CommonDbContext() : base() { } public CommonDbContext(DbContextOptions options) : base(options) { } public abstract CommonDbContext CreateCopy(); public async Task ApiSaveChangesAsync() { try { await SaveChangesAsync(); return true; } catch (Exception ex) { Console.WriteLine("Error saving db: " + ex.Message); Console.WriteLine(ex.StackTrace); return false; } } public static BadRequest SaveError = TypedResults.BadRequest(new Error { Message = "Error saving data to database" }); public async Task, T1>> ApiSaveChangesAsync(T1 value) where T1 : IResult { var res = await ApiSaveChangesAsync(); if (res) return value; else return SaveError; } public async Task, CreatedAtRoute>> ApiSaveChangesAsyncCreate(IServiceProvider providers, T1 value, bool apply = true) where T2 : IAutomappedAttribute, new() { if (!apply) return TypedResults.CreatedAtRoute(new T2().ApplyFrom(providers, value)); var res = await ApiSaveChangesAsync(); if (res) return TypedResults.CreatedAtRoute(new T2().ApplyFrom(providers, value)); else return SaveError; } public async Task, Ok>> ApiSaveChangesAsyncOk(IServiceProvider providers, T1 value, bool apply = true) where T2 : IAutomappedAttribute, new() { if (!apply) return TypedResults.Ok(new T2().ApplyFrom(providers, value)); var res = await ApiSaveChangesAsync(); if (res) return TypedResults.Ok(new T2().ApplyFrom(providers, value)); else return SaveError; } public async Task FindOrCreateAsync(Expression> predicate, Func factory) where T : class { var entity = ChangeTracker.Entries().Select(x => x.Entity).FirstOrDefault(predicate.Compile()); //find in change tracker if (entity != null && Entry(entity).State == EntityState.Deleted) { Entry(entity).State = EntityState.Modified; } //find in currentDb if (entity == null) { entity = await Set().FirstOrDefaultAsync(predicate); } //find in up-to-date db if (entity == null) { var newAppDB = CreateCopy(); entity = await newAppDB.Set().FirstOrDefaultAsync(predicate); //track the entity if it's not null and not already being tracked if (entity != null && this.Entry(entity).State == EntityState.Detached) Attach(entity); } //create if not found if (entity == null) { var newEntity = factory(); await this.AddAsync(newEntity); entity = newEntity; } return entity; } public T FindOrCreate(Expression> predicate, Func factory) where T : class { var entity = ChangeTracker.Entries().Where(e => e.State != EntityState.Deleted).Select(x => x.Entity).FirstOrDefault(predicate.Compile()); //find in change tracker if (entity != null && Entry(entity).State == EntityState.Deleted) { Entry(entity).State = EntityState.Modified; } //find in currentDb if (entity == null) { entity = Set().FirstOrDefault(predicate); } //find in up-to-date db if (entity == null) { var newAppDB = CreateCopy(); entity = newAppDB.Set().FirstOrDefault(predicate); if (entity != null) Attach(entity); } //create if not found if (entity == null) { var newEntity = factory(); this.Add(newEntity); entity = newEntity; } return entity; } public T Create(Action config = null, params object[] constructorArguments) { var entity = this.CreateProxy(constructorArguments); config?.Invoke(entity); this.Add(entity); this.ChangeTracker.DetectChanges(); return entity; } public void ApplyRelationships() { this.ChangeTracker.DetectChanges(); } }