You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

LuEfCrudBusiness.cs 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Linq.Expressions;
  5. using Luticate2.Auth.Dbo;
  6. using Luticate2.Auth.Dbo.Fields;
  7. using Luticate2.Auth.Dbo.Pagination;
  8. using Luticate2.Auth.Dbo.PartialObjectCopier;
  9. using Luticate2.Auth.Dbo.Result;
  10. using Luticate2.Auth.Interfaces;
  11. using Microsoft.EntityFrameworkCore;
  12. using Microsoft.Extensions.DependencyInjection;
  13. namespace Luticate2.Auth.Business.Crud
  14. {
  15. public class LuEfCrudBusiness<TDbo, TModel, TDbContext> : ILuCrud<TDbo>
  16. where TModel : class
  17. where TDbContext : DbContext
  18. where TDbo : new()
  19. {
  20. protected IServiceProvider ServiceProvider { get; }
  21. public LuEfCrudBusiness(IServiceProvider serviceProvider)
  22. {
  23. ServiceProvider = serviceProvider;
  24. }
  25. protected virtual LuResult<TModel> ConvertDboToModel(LuPartialFieldsDbo partialInput, TDbo dbo, TModel model)
  26. {
  27. var copier = ServiceProvider.GetService<ILuPartialObjectCopier<TDbo, TModel>>();
  28. if (copier == null)
  29. {
  30. return LuResult<TModel>.Error(LuStatus.InternalError.ToInt(), $"Could not get service: ILuPartialObjectCopier<{typeof(TDbo).Name}, {typeof(TModel).Name}>");
  31. }
  32. var result = copier.Copy(partialInput, dbo, model, new LuPartialObjectCopierOptions());
  33. return result;
  34. }
  35. protected virtual LuResult<TDbo> ConvertModelToDbo(LuPartialFieldsDbo partialResponse, TModel model, TDbo dbo)
  36. {
  37. var copier = ServiceProvider.GetService<ILuPartialObjectCopier<TModel, TDbo>>();
  38. if (copier == null)
  39. {
  40. return LuResult<TDbo>.Error(LuStatus.InternalError.ToInt(), $"Could not get service: ILuPartialObjectCopier<{typeof(TModel).Name}, {typeof(TDbo).Name}>");
  41. }
  42. var result = copier.Copy(partialResponse, model, dbo, new LuPartialObjectCopierOptions());
  43. return result;
  44. }
  45. protected virtual LuResult<T> HandleError<T>(Exception e)
  46. {
  47. return LuResult<T>.Error(LuStatus.DbError.ToInt(), e);
  48. }
  49. protected LuResult<T> Execute<T>(Func<TDbContext, DbSet<TModel>, LuResult<T>> action)
  50. {
  51. try
  52. {
  53. using (var db = ServiceProvider.GetService<TDbContext>())
  54. {
  55. return action(db, db.Set<TModel>());
  56. }
  57. }
  58. catch (Exception e)
  59. {
  60. var result = HandleError<T>(e);
  61. return result;
  62. }
  63. }
  64. protected virtual LuResult<IQueryable<TModel>> Include(LuPartialFieldsDbo partialResponse, IQueryable<TModel> queryable)
  65. {
  66. return LuResult<IQueryable<TModel>>.Ok(queryable);
  67. }
  68. protected virtual LuResult<IQueryable<TModel>> Filter(LuFilterDbo filter, IQueryable<TModel> queryable)
  69. {
  70. return LuResult<IQueryable<TModel>>.Ok(queryable.Where((Expression<Func<TModel, bool>>) filter.Expression));
  71. }
  72. protected IQueryable<TModel> ConvertAndOrderByQueryable<T>(Expression<Func<TModel, object>> exp,
  73. LuOrderByFieldDbo orderByfield, IQueryable<TModel> queryable, Expression expressionNoConvert)
  74. {
  75. var ordered = queryable as IOrderedQueryable<TModel>;
  76. var expType = expressionNoConvert.Type;
  77. var type = typeof(T);
  78. if (type.IsAssignableFrom(expType))
  79. {
  80. var expLambda = Expression.Lambda<Func<TModel, T>>(expressionNoConvert, exp.Parameters);
  81. if (ordered != null)
  82. {
  83. ordered = orderByfield.Asc ? ordered.ThenBy(expLambda) : ordered.ThenByDescending(expLambda);
  84. }
  85. else
  86. {
  87. ordered = orderByfield.Asc ? queryable.OrderBy(expLambda) : queryable.OrderByDescending(expLambda);
  88. }
  89. }
  90. return ordered ?? queryable;
  91. }
  92. protected virtual LuResult<IQueryable<TModel>> OrderByField(LuOrderByFieldDbo orderByfield, IQueryable<TModel> queryable)
  93. {
  94. var expressionBuilder = ServiceProvider.GetService<ILuFieldsExpressions<TDbo, TModel>>();
  95. var expressionResult = expressionBuilder.GetExpression<TModel>(x => x, orderByfield.Field);
  96. if (!expressionResult)
  97. {
  98. return expressionResult.To<IQueryable<TModel>>();
  99. }
  100. var expression = expressionResult.Data;
  101. var expressionNoConvert = LuExpressionUtils.GetFromConvert(expression);
  102. var ordered = ConvertAndOrderByQueryable<bool>(expression, orderByfield, queryable, expressionNoConvert);
  103. ordered = ConvertAndOrderByQueryable<byte>(expression, orderByfield, ordered, expressionNoConvert);
  104. ordered = ConvertAndOrderByQueryable<DateTime>(expression, orderByfield, ordered, expressionNoConvert);
  105. ordered = ConvertAndOrderByQueryable<DateTimeOffset>(expression, orderByfield, ordered, expressionNoConvert);
  106. ordered = ConvertAndOrderByQueryable<decimal>(expression, orderByfield, ordered, expressionNoConvert);
  107. ordered = ConvertAndOrderByQueryable<double>(expression, orderByfield, ordered, expressionNoConvert);
  108. ordered = ConvertAndOrderByQueryable<float>(expression, orderByfield, ordered, expressionNoConvert);
  109. ordered = ConvertAndOrderByQueryable<Guid>(expression, orderByfield, ordered, expressionNoConvert);
  110. ordered = ConvertAndOrderByQueryable<short>(expression, orderByfield, ordered, expressionNoConvert);
  111. ordered = ConvertAndOrderByQueryable<int>(expression, orderByfield, ordered, expressionNoConvert);
  112. ordered = ConvertAndOrderByQueryable<long>(expression, orderByfield, ordered, expressionNoConvert);
  113. ordered = ConvertAndOrderByQueryable<char>(expression, orderByfield, ordered, expressionNoConvert);
  114. ordered = ConvertAndOrderByQueryable<string>(expression, orderByfield, ordered, expressionNoConvert);
  115. return LuResult<IQueryable<TModel>>.Ok(ordered);
  116. }
  117. protected virtual LuResult<IQueryable<TModel>> OrderBy(LuOrderByDbo orderBy, IQueryable<TModel> queryable)
  118. {
  119. var ordered = queryable;
  120. foreach (var field in orderBy.OrderByFields)
  121. {
  122. var orderedResult = OrderByField(field, ordered);
  123. if (!orderedResult)
  124. {
  125. return orderedResult.To<IQueryable<TModel>>();
  126. }
  127. ordered = orderedResult.Data;
  128. }
  129. return LuResult<IQueryable<TModel>>.Ok(ordered ?? queryable);
  130. }
  131. protected virtual LuResult<IQueryable<TModel>> Paginate(int page, int perPage, IQueryable<TModel> queryable)
  132. {
  133. var paginated = queryable.Skip(page * perPage).Take(perPage);
  134. return LuResult<IQueryable<TModel>>.Ok(paginated);
  135. }
  136. public virtual LuResult<IList<TDbo>> Create(LuPartialFieldsDbo partialResponse, LuPartialFieldsDbo partialInput, IEnumerable<TDbo> dbos)
  137. {
  138. throw new NotImplementedException();
  139. }
  140. public virtual LuResult<LuPaginatedDbo<TDbo>> Read(LuPartialFieldsDbo partialResponse, LuPaginatedParamsDbo paginationParams)
  141. {
  142. var result = Execute((context, set) =>
  143. {
  144. var includeResult = Include(partialResponse, set);
  145. if (!includeResult)
  146. {
  147. return includeResult.To<LuPaginatedDbo<TDbo>>();
  148. }
  149. var included = includeResult.Data;
  150. var orderByResult = OrderBy(paginationParams.OrderBy, included);
  151. if (!orderByResult)
  152. {
  153. return orderByResult.To<LuPaginatedDbo<TDbo>>();
  154. }
  155. var ordered = orderByResult.Data;
  156. var filteredResult = Filter(paginationParams.Filter, ordered);
  157. if (!filteredResult)
  158. {
  159. return filteredResult.To<LuPaginatedDbo<TDbo>>();
  160. }
  161. var filtered = filteredResult.Data;
  162. var count = filtered.Count();
  163. var paginatedResult = Paginate(paginationParams.Page, paginationParams.PerPage, filtered);
  164. if (!paginatedResult)
  165. {
  166. return paginatedResult.To<LuPaginatedDbo<TDbo>>();
  167. }
  168. var paginated = paginatedResult.Data;
  169. var data = paginated.AsEnumerable().Select(model =>
  170. {
  171. var dbo = new TDbo();
  172. ConvertModelToDbo(partialResponse, model, dbo);
  173. return dbo;
  174. }).ToList();
  175. return LuResult<LuPaginatedDbo<TDbo>>.Ok(new LuPaginatedDbo<TDbo>
  176. {
  177. Count = count,
  178. Data = data
  179. });
  180. });
  181. return result;
  182. }
  183. public virtual LuResult<IList<TDbo>> Update(LuPartialFieldsDbo partialResponse, LuPartialFieldsDbo partialInput, IEnumerable<TDbo> dbos)
  184. {
  185. throw new NotImplementedException();
  186. }
  187. public virtual LuResult<IList<TDbo>> Delete(LuPartialFieldsDbo partialResponse, LuPartialFieldsDbo partialInput, IEnumerable<TDbo> dbos)
  188. {
  189. throw new NotImplementedException();
  190. }
  191. }
  192. }