using LANCommander.Server.Data; using LANCommander.Server.Data.Enums; using LANCommander.Server.Data.Models; using LANCommander.Server.Models; using LANCommander.Server.Services.Models; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; using Microsoft.Extensions.Logging; using System.Linq.Expressions; using ZiggyCreatures.Caching.Fusion; namespace LANCommander.Server.Services { public abstract class BaseDatabaseService : BaseService, IBaseDatabaseService where T : class, IBaseModel { protected readonly IFusionCache Cache; protected Repository Repository { get; set; } public BaseDatabaseService( ILogger logger, IFusionCache cache, RepositoryFactory repositoryFactory) : base(logger) { Cache = cache; Repository = repositoryFactory.Create(); } public IBaseDatabaseService AsNoTracking() { Repository.AsNoTracking(); return this; } public IBaseDatabaseService Query(Func, IQueryable> modifier) { Repository.Query(modifier); return this; } public IBaseDatabaseService Include(params Expression>[] expressions) { Repository.Include(expressions); return this; } public IBaseDatabaseService SortBy(Expression> expression, SortDirection direction = SortDirection.Ascending) { Repository.SortBy(expression, direction); return this; } public IBaseDatabaseService DisableTracking() { Repository.AsNoTracking(); return this; } public async Task> PaginateAsync(Expression> expression, int pageNumber, int pageSize) { return await Repository.PaginateAsync(expression, pageNumber, pageSize); } public virtual async Task> GetAsync() { return await GetAsync(x => true); } public virtual async Task> GetAsync() { return await GetAsync(x => true); } public virtual async Task GetAsync(Guid id) { return await Repository.FindAsync(id); } public virtual async Task GetAsync(Guid id) { return await Repository.FindAsync(id); } public virtual async Task> GetAsync(Expression> predicate) { var results = await Repository.GetAsync(predicate); return results; } public virtual async Task> GetAsync(Expression> predicate) { var results = await Repository.GetAsync(predicate); return results; } public virtual async Task FirstAsync(Expression> predicate) { return await Repository.FirstAsync(predicate); } public virtual async Task FirstAsync(Expression> predicate) { return await Repository.FirstAsync(predicate); } public virtual async Task FirstAsync(Expression> predicate, Expression> orderKeySelector) { return await Repository.FirstAsync(predicate, orderKeySelector); } public virtual async Task FirstAsync(Expression> predicate, Expression> orderKeySelector) { return await Repository.FirstAsync(predicate, orderKeySelector); } public virtual async Task FirstOrDefaultAsync(Expression> predicate) { return await Repository.FirstOrDefaultAsync(predicate); } public virtual async Task FirstOrDefaultAsync(Expression> predicate) { return await Repository.FirstOrDefaultAsync(predicate); } public virtual async Task FirstOrDefaultAsync(Expression> predicate, Expression> orderKeySelector) { return await Repository.FirstOrDefaultAsync(predicate, orderKeySelector); } public virtual async Task FirstOrDefaultAsync(Expression> predicate, Expression> orderKeySelector) { return await Repository.FirstOrDefaultAsync(predicate, orderKeySelector); } public virtual async Task ExistsAsync(Guid id) { return (await FirstOrDefaultAsync(x => x.Id == id)) != null; } public virtual async Task ExistsAsync(Expression> predicate) { return (await GetAsync(predicate)) != null; } public virtual async Task AddAsync(T entity) { entity = await Repository.AddAsync(entity); await Repository.SaveChangesAsync(); return entity; } /// /// Adds an entity to the database if it does exist as dictated by the predicate /// /// Qualifier expressoin /// Entity to add /// Newly created or existing entity public virtual async Task> AddMissingAsync(Expression> predicate, T entity) { var existing = await Repository.FirstOrDefaultAsync(predicate); if (existing == null) { await Cache.ExpireAsync($"{typeof(T).FullName}:Get"); entity = await Repository.AddAsync(entity); await Repository.SaveChangesAsync(); return new ExistingEntityResult { Value = entity, Existing = false }; } else { return new ExistingEntityResult { Value = existing, Existing = true }; } } public virtual async Task UpdateAsync(T entity) { entity = await Repository.UpdateAsync(entity); await Repository.SaveChangesAsync(); return entity; } public virtual async Task DeleteAsync(T entity) { await Cache.ExpireAsync($"{typeof(T).FullName}:Get"); Repository.Delete(entity); await Repository.SaveChangesAsync(); } public void Dispose() { /*if (Repository != null) { Repository.Dispose(); Repository = null; }*/ } } }