using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using Luticate2.Utils.Dbo; using Microsoft.EntityFrameworkCore; namespace Luticate2.Utils.DataAccess { public abstract class LuEfCrudDataAccess : LuEfDataAccess where TModel : class where TDboCreate : class where TDboRead : class where TDboUpdate : class where TDbContext : DbContext { protected LuEfCrudDataAccess(TDbContext db, DbSet table) : base(db, table) { } protected abstract TModel GetModelFromTCreate(TDboCreate obj); protected abstract void EditModelFromTUpdate(TDboUpdate obj, TModel model); protected abstract TDboRead GetDboFromModel(TModel model); public Func GetIdFunc() { var param = Expression.Parameter(typeof(TDboRead), "x"); var exp = Expression.Property(param, "Id"); var lambda = Expression.Lambda>(exp, param); var func = lambda.Compile(); return func; } protected TModel GetModelFromTUpdate(TDboUpdate obj, TModel model) { EditModelFromTUpdate(obj, model); return model; } public LuResult Add(IEnumerable objs, Func, T> returnFunc) { return Execute(() => { var models = objs.Select(GetModelFromTCreate).ToList(); Table.AddRange(models); Db.SaveChanges(); var dbos = models.Select(GetDboFromModel).ToList(); var res = returnFunc(dbos); return LuResult.Ok(res); }); } public LuResult Add(TDboCreate obj, Func returnFunc) { return Add(new List {obj}, list => returnFunc(list.First())); } public LuResult> AddGuid(IEnumerable objs) { var func = GetIdFunc(); return Add(objs, list => list.Select(func)); } public LuResult AddGuid(TDboCreate obj) { return AddGuid(new List {obj}).To(list => list.First()); } public LuResult> AddId(IEnumerable obj) { var func = GetIdFunc(); return Add(obj, list => list.Select(func)); } public LuResult AddId(TDboCreate obj) { return AddId(new List {obj}).To(list => list.First()); } public LuResult> AddDbo(IEnumerable obj) { return Add(obj, read => read); } public LuResult AddDbo(TDboCreate obj) { return AddDbo(new List {obj}).To(list => list.First()); } public LuResult GetSingle(Expression> predicate) { return Execute(() => { var model = Table.FirstOrDefault(predicate); if (model == null) { return LuResult.Error(LuStatus.NotFound, typeof(TModel).Name + ": Value not found", ""); } var dbo = GetDboFromModel(model); return LuResult.Ok(dbo); }); } public LuResult GetSingleByKeys(params KeyValuePair[] keys) { return GetSingle(GetExpression(keys)); } public LuResult GetSingleById(string id) { return GetSingleByKeys(new KeyValuePair("id", new Guid(id))); } public LuResult GetSingleById(long id) { return GetSingleByKeys(new KeyValuePair("id", id)); } public LuResult> GetMultiple(Func> orderBy, Expression> predicate, int page = 0, int perPage = int.MaxValue, params Expression>[] otherOrderBy) { return Execute(() => { var count = Table.Count(predicate); var ordered = orderBy(); var data = ordered.Where(predicate).Skip(page * perPage).Take(perPage).Select(GetDboFromModel).ToList(); var result = new LuPaginatedDbo { Count = count, Data = data }; return LuResult>.Ok(result); }); } public LuResult> GetMultiple(Expression> orderBy, Expression> predicate, int page = 0, int perPage = int.MaxValue) { return GetMultiple(() => Table.OrderBy(orderBy), predicate, page, perPage); } public LuResult> GetMultiple(Expression> orderBy, int page = 0, int perPage = int.MaxValue, params Expression>[] otherOrderBy) { return GetMultiple(() => Table.OrderBy(orderBy), x => true, page, perPage, otherOrderBy); } public LuResult> GetMultiple(Expression> orderBy, int page = 0, int perPage = int.MaxValue) { return GetMultiple(orderBy, x => true, page, perPage); } public LuResult Edit(Expression> predicate, Action update, Func, T> returnFunc) { return Execute(() => { var models = Table.Where(predicate); var editedDbos = new List(); foreach (var model in models) { update(model); editedDbos.Add(GetDboFromModel(model)); Db.Entry(model).State = EntityState.Modified; } Db.SaveChanges(); var res = returnFunc(editedDbos); return LuResult.Ok(res); }); } public LuResult> EditGuid(Expression> predicate, Action update) { var func = GetIdFunc(); return Edit(predicate, update, reads => reads.Select(func)); } public LuResult> EditId(Expression> predicate, Action update) { var func = GetIdFunc(); return Edit(predicate, update, reads => reads.Select(func)); } public LuResult> EditDbo(Expression> predicate, Action update) { return Edit(predicate, update, read => read); } public LuResult EditSingleById(long id, Action update, Func returnFunc) { return Edit(GetExpression(new KeyValuePair("id", id)), update, list => returnFunc(list.FirstOrDefault())); } public LuResult EditSingleByIdGuid(long id, Action update) { var func = GetIdFunc(); return EditSingleById(id, update, func); } public LuResult EditSingleByIdId(long id, Action update) { var func = GetIdFunc(); return EditSingleById(id, update, func); } public LuResult EditSingleByIdDbo(long id, Action update) { return EditSingleById(id, update, read => read); } public LuResult EditSingleById(string id, Action update, Func returnFunc) { return Edit(GetExpression(new KeyValuePair("id", new Guid(id))), update, list => returnFunc(list.FirstOrDefault())); } public LuResult EditSingleByIdGuid(string id, Action update) { return EditSingleById(id, update, GetIdFunc()); } public LuResult EditSingleByIdId(string id, Action update) { return EditSingleById(id, update, GetIdFunc()); } public LuResult EditSingleByIdDbo(string id, Action update) { return EditSingleById(id, update, read => read); } public LuResult EditSingleById(long id, TDboUpdate update, Func returnFunc) { return Edit(GetExpression(new KeyValuePair("id", id)), model => EditModelFromTUpdate(update, model), list => returnFunc(list.FirstOrDefault())); } public LuResult EditSingleByIdGuid(long id, TDboUpdate update) { return EditSingleById(id, update, GetIdFunc()); } public LuResult EditSingleByIdId(long id, TDboUpdate update) { return EditSingleById(id, update, GetIdFunc()); } public LuResult EditSingleByIdDbo(long id, TDboUpdate update) { return EditSingleById(id, update, read => read); } public LuResult EditSingleById(string id, TDboUpdate update, Func returnFunc) { return Edit(GetExpression(new KeyValuePair("id", id)), model => EditModelFromTUpdate(update, model), list => returnFunc(list.FirstOrDefault())); } public LuResult EditSingleByIdGuid(string id, TDboUpdate update) { return EditSingleById(id, update, GetIdFunc()); } public LuResult EditSingleByIdId(string id, TDboUpdate update) { return EditSingleById(id, update, GetIdFunc()); } public LuResult EditSingleByIdDbo(string id, TDboUpdate update) { return EditSingleById(id, update, read => read); } public LuResult Delete(Expression> predicate, Func, T> returnFunc) { return Execute(() => { var models = Table.Where(predicate).ToList(); Table.RemoveRange(models); Db.SaveChanges(); var dbos = models.Select(GetDboFromModel); return LuResult.Ok(returnFunc(dbos)); }); } public LuResult> DeleteGuid(Expression> predicate) { var func = GetIdFunc(); return Delete(predicate, reads => reads.Select(func)); } public LuResult> DeleteId(Expression> predicate) { var func = GetIdFunc(); return Delete(predicate, reads => reads.Select(func)); } public LuResult> DeleteDbo(Expression> predicate) { return Delete(predicate, read => read); } public LuResult DeleteSingleById(string id, Func returnFunc) { return Delete(GetExpression(new KeyValuePair("id", new Guid(id))), reads => returnFunc(reads.First())); } public LuResult DeleteSingleByIdGuid(string id) { var func = GetIdFunc(); return DeleteSingleById(id, func); } public LuResult DeleteSingleByIdId(string id) { var func = GetIdFunc(); return DeleteSingleById(id, func); } public LuResult DeleteSingleByIdDbo(string id) { return DeleteSingleById(id, read => read); } public LuResult DeleteSingleById(long id, Func returnFunc) { return Delete(GetExpression(new KeyValuePair("id", id)), reads => returnFunc(reads.First())); } public LuResult DeleteSingleByGuid(long id) { var func = GetIdFunc(); return DeleteSingleById(id, func); } public LuResult DeleteSingleByIdId(long id) { var func = GetIdFunc(); return DeleteSingleById(id, func); } public LuResult DeleteSingleByIdDbo(long id) { return DeleteSingleById(id, read => read); } } }