using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using Luticate2.Auth.Utils.Business.Converters; using Luticate2.Auth.Utils.Business.ExpressionConverter; using Luticate2.Auth.Utils.Dbo; using Luticate2.Auth.Utils.Dbo.Fields; using Luticate2.Auth.Utils.Dbo.Pagination; using Luticate2.Auth.Utils.Dbo.Result; using Luticate2.Auth.Utils.Interfaces; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; namespace Luticate2.Auth.Utils.Business.Crud { public class LuEfCrudBusiness : ILuCrud where TModel : class where TDbContext : DbContext where TDbo : class, new() { protected IServiceProvider ServiceProvider { get; } public LuEfCrudBusiness(IServiceProvider serviceProvider) { ServiceProvider = serviceProvider; } protected virtual ILuObjectConverterOptions GetOptions() { return new LuConvertersOptions();// TODO } protected virtual LuResult ConvertDboToModel(LuPartialFieldsDbo partialInput, TDbo dbo) { var copier = ServiceProvider.GetService>(); if (copier == null) { return LuResult.Error(LuStatus.InternalError.ToInt(), $"Could not get service: {nameof(ILuObjectConverter)}<{typeof(TDbo).Name}, {typeof(TModel).Name}>"); } var result = copier.Convert(dbo, new LuFieldDbo(), partialInput, GetOptions()); return result.Select(o => o as TModel); } protected virtual LuResult ConvertModelToDbo(LuPartialFieldsDbo partialResponse, TModel model) { var copier = ServiceProvider.GetService>(); if (copier == null) { return LuResult.Error(LuStatus.InternalError.ToInt(), $"Could not get service: {nameof(ILuObjectConverter)}<{typeof(TModel).Name}, {typeof(TDbo).Name}>"); } var result = copier.Convert(model, new LuFieldDbo(), partialResponse, GetOptions()); return result.Select(o => o as TDbo); } 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) { var lamdbaDbo = (Expression>) filter.Expression; var options = new LuConvertersOptions { Parameters = new Dictionary(), // TODO TypeConverter = null, // TODO Allocator = null // TODO }; var converter = new LuExpressionConverterVisitor(options, ServiceProvider); var lamdbaModel = converter.Visit(lamdbaDbo) as Expression>;// TODO Handle errors return LuResult>.Ok(queryable.Where(lamdbaModel)); } protected virtual LuResult> OrderByField(LuOrderByFieldDbo orderByfield, IQueryable queryable) { // var expressionBuilder = ServiceProvider.GetService>(); // var expressionResult = expressionBuilder.ConvertLamdba(orderByfield.); // if (!expressionResult) // { // return expressionResult.To>(); // } // // var expression = expressionResult.Data; // var expressionNoConvert = LuExpressionUtils.GetFromConvert(expression); // // var ordered = queryable.OrderBy(expressionNoConvert); // // return LuResult>.Ok(ordered); return LuResult>.Ok(queryable); } 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 convertResult = ConvertModelToDbo(partialResponse, model); // TODO Handle error return convertResult.Data; }).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(); } } }