NejCommon.NET/Models/CommonDbContext.cs
2025-06-20 20:34:03 +02:00

204 lines
6.1 KiB
C#

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<bool> 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<Error> SaveError = TypedResults.BadRequest(new Error
{
Message = "Error saving data to database"
});
public async Task<Results<BadRequest<Error>, T1>> ApiSaveChangesAsync<T1>(T1 value) where T1 : IResult
{
var res = await ApiSaveChangesAsync();
if (res)
return value;
else
return SaveError;
}
public async Task<Results<BadRequest<Error>, CreatedAtRoute<T2>>> ApiSaveChangesAsyncCreate<T1, T2>(IServiceProvider providers, T1 value, bool apply = true, T2? response = null) where T2 : class, IAutomappedAttribute<T1, T2>, new()
{
if(response == null)
response = new T2();
if (!apply)
return TypedResults.CreatedAtRoute(response.ApplyFrom(providers, value));
var res = await ApiSaveChangesAsync();
if (res)
return TypedResults.CreatedAtRoute(response.ApplyFrom(providers, value));
else
return SaveError;
}
public async Task<Results<BadRequest<Error>, Ok<T2>>> ApiSaveChangesAsyncOk<T1, T2>(IServiceProvider providers, T1 value, bool apply = true, T2? response = null) where T2 : class, IAutomappedAttribute<T1, T2>, new()
{
if(response == null)
response = new T2();
if (!apply)
return TypedResults.Ok(response.ApplyFrom(providers, value));
var res = await ApiSaveChangesAsync();
if (res)
return TypedResults.Ok(response.ApplyFrom(providers, value));
else
return SaveError;
}
public async Task<Results<BadRequest<Error>, Ok<List<T2>>>> ApiSaveChangesAsyncOk<T1, T2>(IServiceProvider providers, IEnumerable<T1> value, bool apply = true, T2? response = null) where T2 : class, IAutomappedAttribute<T1, T2>, new()
{
if(response == null)
response = new T2();
if (!apply)
return TypedResults.Ok(value.Select(x=> new T2().ApplyFrom(providers, x)).ToList());
var res = await ApiSaveChangesAsync();
if (res)
return TypedResults.Ok(value.Select(x=> new T2().ApplyFrom(providers, x)).ToList());
else
return SaveError;
}
public async Task<Results<BadRequest<Error>, Ok>> ApiSaveChangesAsyncOk()
{
var res = await ApiSaveChangesAsync();
if (res)
return TypedResults.Ok();
else
return SaveError;
}
public async Task<T> FindOrCreateAsync<T>(Expression<Func<T, bool>> predicate, Func<T> factory) where T : class
{
var entity = ChangeTracker.Entries<T>().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<T>().FirstOrDefaultAsync(predicate);
}
//find in up-to-date db
if (entity == null)
{
var newAppDB = CreateCopy();
entity = await newAppDB.Set<T>().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<T>(Expression<Func<T, bool>> predicate, Func<T> factory) where T : class
{
var entity = ChangeTracker.Entries<T>().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<T>().FirstOrDefault(predicate);
}
//find in up-to-date db
if (entity == null)
{
var newAppDB = CreateCopy();
entity = newAppDB.Set<T>().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<T>(Action<T> config = null, params object[] constructorArguments)
{
var entity = this.CreateProxy<T>(constructorArguments);
config?.Invoke(entity);
this.Add(entity);
this.ChangeTracker.DetectChanges();
return entity;
}
public object Create(Type entityType, Action<object> config = null, params object[] constructorArguments)
{
var entity = this.CreateProxy(entityType, constructorArguments);
config?.Invoke(entity);
this.Add(entity);
this.ChangeTracker.DetectChanges();
return entity;
}
public void ApplyRelationships()
{
this.ChangeTracker.DetectChanges();
}
}