using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using Luticate2.Auth.Dbo; using Luticate2.Auth.Dbo.Fields; using Luticate2.Auth.Dbo.Pagination; using Luticate2.Auth.Dbo.PartialObjectCopier; using Luticate2.Auth.Dbo.Result; using Luticate2.Auth.Interfaces; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; namespace Luticate2.Auth.Business.Crud { public class LuEfCrudBusiness : ILuCrud where TModel : class where TDbContext : DbContext where TDbo : new() { protected IServiceProvider ServiceProvider { get; } public LuEfCrudBusiness(IServiceProvider serviceProvider) { ServiceProvider = serviceProvider; } protected virtual LuResult ConvertDboToModel(LuPartialFieldsDbo partialInput, TDbo dbo, TModel model) { var copier = ServiceProvider.GetService>(); if (copier == null) { return LuResult.Error(LuStatus.InternalError.ToInt(), $"Could not get service: ILuPartialObjectCopier<{typeof(TDbo).Name}, {typeof(TModel).Name}>"); } var result = copier.Copy(partialInput, dbo, model, new LuPartialObjectCopierOptions()); return result; } protected virtual LuResult ConvertModelToDbo(LuPartialFieldsDbo partialResponse, TModel model, TDbo dbo) { var copier = ServiceProvider.GetService>(); if (copier == null) { return LuResult.Error(LuStatus.InternalError.ToInt(), $"Could not get service: ILuPartialObjectCopier<{typeof(TModel).Name}, {typeof(TDbo).Name}>"); } var result = copier.Copy(partialResponse, model, dbo, new LuPartialObjectCopierOptions()); return result; } protected virtual LuResult HandleError(Exception e) { return LuResult.Error(LuStatus.DbError.ToInt(), e); } protected LuResult Execute(Func, LuResult> action) { try { using (var db = ServiceProvider.GetService()) { return action(db, db.Set()); } } catch (Exception e) { var result = HandleError(e); return result; } } protected virtual LuResult> Include(LuPartialFieldsDbo partialResponse, IQueryable queryable) { return LuResult>.Ok(queryable); } protected virtual LuResult> Filter(LuFilterDbo filter, IQueryable queryable) { return LuResult>.Ok(queryable.Where((Expression>) filter.Expression)); } protected IQueryable ConvertAndOrderByQueryable(Expression> exp, LuOrderByFieldDbo orderByfield, IQueryable queryable, Expression expressionNoConvert) { var ordered = queryable as IOrderedQueryable; var expType = expressionNoConvert.Type; var type = typeof(T); if (type.IsAssignableFrom(expType)) { var expLambda = Expression.Lambda>(expressionNoConvert, exp.Parameters); if (ordered != null) { ordered = orderByfield.Asc ? ordered.ThenBy(expLambda) : ordered.ThenByDescending(expLambda); } else { ordered = orderByfield.Asc ? queryable.OrderBy(expLambda) : queryable.OrderByDescending(expLambda); } } return ordered ?? queryable; } protected virtual LuResult> OrderByField(LuOrderByFieldDbo orderByfield, IQueryable queryable) { var expressionBuilder = ServiceProvider.GetService>(); var expressionResult = expressionBuilder.GetExpression(x => x, orderByfield.Field); if (!expressionResult) { return expressionResult.To>(); } var expression = expressionResult.Data; var expressionNoConvert = LuExpressionUtils.GetFromConvert(expression); var ordered = ConvertAndOrderByQueryable(expression, orderByfield, queryable, expressionNoConvert); ordered = ConvertAndOrderByQueryable(expression, orderByfield, ordered, expressionNoConvert); ordered = ConvertAndOrderByQueryable(expression, orderByfield, ordered, expressionNoConvert); ordered = ConvertAndOrderByQueryable(expression, orderByfield, ordered, expressionNoConvert); ordered = ConvertAndOrderByQueryable(expression, orderByfield, ordered, expressionNoConvert); ordered = ConvertAndOrderByQueryable(expression, orderByfield, ordered, expressionNoConvert); ordered = ConvertAndOrderByQueryable(expression, orderByfield, ordered, expressionNoConvert); ordered = ConvertAndOrderByQueryable(expression, orderByfield, ordered, expressionNoConvert); ordered = ConvertAndOrderByQueryable(expression, orderByfield, ordered, expressionNoConvert); ordered = ConvertAndOrderByQueryable(expression, orderByfield, ordered, expressionNoConvert); ordered = ConvertAndOrderByQueryable(expression, orderByfield, ordered, expressionNoConvert); ordered = ConvertAndOrderByQueryable(expression, orderByfield, ordered, expressionNoConvert); ordered = ConvertAndOrderByQueryable(expression, orderByfield, ordered, expressionNoConvert); return LuResult>.Ok(ordered); } protected virtual LuResult> OrderBy(LuOrderByDbo orderBy, IQueryable queryable) { var ordered = queryable; foreach (var field in orderBy.OrderByFields) { var orderedResult = OrderByField(field, ordered); if (!orderedResult) { return orderedResult.To>(); } ordered = orderedResult.Data; } return LuResult>.Ok(ordered ?? queryable); } protected virtual LuResult> Paginate(int page, int perPage, IQueryable queryable) { var paginated = queryable.Skip(page * perPage).Take(perPage); return LuResult>.Ok(paginated); } public virtual LuResult> Create(LuPartialFieldsDbo partialResponse, LuPartialFieldsDbo partialInput, IEnumerable dbos) { throw new NotImplementedException(); } public virtual LuResult> Read(LuPartialFieldsDbo partialResponse, LuPaginatedParamsDbo paginationParams) { var result = Execute((context, set) => { var includeResult = Include(partialResponse, set); if (!includeResult) { return includeResult.To>(); } var included = includeResult.Data; var orderByResult = OrderBy(paginationParams.OrderBy, included); if (!orderByResult) { return orderByResult.To>(); } var ordered = orderByResult.Data; var filteredResult = Filter(paginationParams.Filter, ordered); if (!filteredResult) { return filteredResult.To>(); } var filtered = filteredResult.Data; var count = filtered.Count(); var paginatedResult = Paginate(paginationParams.Page, paginationParams.PerPage, filtered); if (!paginatedResult) { return paginatedResult.To>(); } var paginated = paginatedResult.Data; var data = paginated.AsEnumerable().Select(model => { var dbo = new TDbo(); ConvertModelToDbo(partialResponse, model, dbo); return dbo; }).ToList(); return LuResult>.Ok(new LuPaginatedDbo { Count = count, Data = data }); }); return result; } public virtual LuResult> Update(LuPartialFieldsDbo partialResponse, LuPartialFieldsDbo partialInput, IEnumerable dbos) { throw new NotImplementedException(); } public virtual LuResult> Delete(LuPartialFieldsDbo partialResponse, LuPartialFieldsDbo partialInput, IEnumerable dbos) { throw new NotImplementedException(); } } }