2025-03-02 12:51:02 +01:00

112 lines
3.1 KiB
C#

using LanguageExt.Common;
using Microsoft.EntityFrameworkCore;
using W542.GandalfReborn.Data.Entities.Base;
using W542.GandalfReborn.Data.Entities.Tenant;
namespace W542.GandalfReborn.Data.Database.Repositories;
public abstract class GrRepository<TEntity>(ApplicationContext context) : IGrRepository<TEntity> where TEntity : class, IEntity
{
public async Task<Result<bool>> SaveChanges()
{
try
{
await context.SaveChangesAsync();
return true;
}
catch (Exception e)
{
return new Result<bool>(e);
}
}
public async Task<Result<TEntity>> GetSingle(Func<IQueryable<TEntity>, IQueryable<TEntity>>? query, bool tracked = true)
{
IQueryable<TEntity> set = context.Set<TEntity>();
if (query is not null)
{
set = query.Invoke(set);
}
if (!tracked)
{
set = set.AsNoTracking();
}
var result = await set.SingleOrDefaultAsync();
return result ?? new Result<TEntity>(new Exception("Not found."));
}
public async Task<Result<ICollection<TEntity>>> GetMany(Func<IQueryable<TEntity>, IQueryable<TEntity>>? query, bool tracked = true)
{
IQueryable<TEntity> set = context.Set<TEntity>();
if (query is not null)
{
set = query.Invoke(set);
}
if (!tracked)
{
set = set.AsNoTracking();
}
var result = await set.ToListAsync();
return result;
}
public async Task<Result<TEntity>> Upsert(TEntity entity)
{
var result = await Upsert([entity]);
return result.Match(
success =>
{
if (success.Count != 1)
{
return new Result<TEntity>(new Exception("Something very sus happened during upsert. Input count != output count?"));
}
return success.Single();
},
fail => new Result<TEntity>(fail)
);
}
public async Task<Result<ICollection<TEntity>>> Upsert(ICollection<TEntity> entities)
{
var newEntities = entities.Where(x => x.Id is null).ToList();
var updatedEntities = entities.Where(x => x.Id is not null).ToList();
try
{
context.AddRange(newEntities);
context.UpdateRange(updatedEntities);
await context.SaveChangesAsync();
}
catch (Exception e)
{
return new Result<ICollection<TEntity>>(e);
}
return new Result<ICollection<TEntity>>(entities);
}
public IQueryable<T> Query<T>(Func<IQueryable<TEntity>, IQueryable<T>> query)
{
return Query<T, TEntity>(query);
}
private IQueryable<TOut> Query<TOut, TIn>(Func<IQueryable<TIn>, IQueryable<TOut>> query) where TIn : class, IEntity
{
IQueryable<TIn> set = context.Set<TIn>();
return query.Invoke(set);
}
public IQueryable<TEntity> Query(Func<IQueryable<TEntity>, IQueryable<TEntity>> query)
{
return Query<TEntity>(query);
}
}