using System; using System.Collections.Generic; using System.Data.Entity; using System.Linq; using System.Linq.Expressions; using System.Runtime.Serialization; using iiie.Logs.DBO; using iiie.WebApiUtils.DBO; namespace iiie.WebApiUtils.BusinessManager { /// /// Helper for SQL Server data access /// public abstract class SqlServerManager : SqlServerBasicManager where TDbObject : class where TEntities : DbContext, new() where TThis : SqlServerManager, new() { /// /// Convert a DB object to DBO /// /// The object to be converted /// The DBO public abstract TDboGet DbToDboGet(TDbObject obj); /// /// Convert a DBO to DB object /// /// The object to be converted /// The object to be added /// The DB object public abstract OpResult DboAddToDb(TDboAdd obj, TDbObject add); /// /// Convert a DBO to DB object /// /// The object to be converted /// The object beeing edited /// The DB object public abstract OpResult DboEditToDb(TDboEdit obj, TDbObject edit); /// /// Return a global predicate that will be applied to all selects /// /// The expression public virtual Expression> GetGlobalSelectPredicate() { return x => true; } /// /// Helper to get real select predicate /// /// The global predicate public static Expression> GetGlobalSelectPredicateStatic() { var obj = new TThis(); return obj.GetGlobalSelectPredicate(); } /// /// Helper to convert DB object to DBO /// /// The result to convert /// The DBO object public static TDboGet DbToDboGetStatic(TDbObject res) { var obj = new TThis(); return obj.DbToDboGet(res); } /// /// Helper to convert DBO object to DB /// /// The result to convert /// The object to be added /// The DB object public static OpResult DboAddToDbStatic(TDboAdd res, TDbObject add) { var obj = new TThis(); return obj.DboAddToDb(res, add); } /// /// Helper to convert DBO object to DB /// /// The result to convert /// The object beeing edited /// The DB object public static OpResult DboEditToDbStatic(TDboEdit res, TDbObject edit) { var obj = new TThis(); return obj.DboEditToDb(res, edit); } /// /// Get a single DB object matching the predicate /// /// The table to search in /// The predicate /// The object that match public static OpResult GetSingleDbObject(DbSet table, Expression> predicate) { var o = table.Where(GetGlobalSelectPredicateStatic()).FirstOrDefault(predicate); if (o == null) { return OpResult.Error(ResultStatus.NotFound, typeof(TThis).Name + ": Value not found", ""); } return OpResult.Ok(o); } /// /// Get a single DBO matching the predicate /// /// The predicate /// The object that match, or null public static OpResult GetSingle(Expression> predicate) { return Execute((db, table) => { var obj = GetSingleDbObject(table, predicate); if (!obj) return obj.To(); return OpResult.Ok(DbToDboGetStatic(obj.Data)); }); } /// /// Get an object by its primary key(s) /// /// The key names and values /// The object public static OpResult GetSingleByKeys(params KeyValuePair[] keys) { return GetSingle(GetExpression(keys)); } /// /// Get an object by its id /// /// The id of the object /// The object public static OpResult GetSingleById(long id) { return GetSingleByKeys(new KeyValuePair("id", id)); } /// /// Get all DB object matching the predicate /// /// The predicate /// The order by function /// The page numeber (0 based) /// The maximum number of items par page /// All matching objects public static OpResult> GetMultiple(Expression> predicate, Expression> orderBy, int page = 0, int perPage = Int32.MaxValue) { return Execute((db, table) => { var globalPredicate = GetGlobalSelectPredicateStatic(); var count = table.Where(globalPredicate).Count(predicate); var results = table.OrderBy(orderBy).Where(globalPredicate).Where(predicate) .Skip(page * perPage).Take(perPage).Select(DbToDboGetStatic).ToList(); var result = new DboGetMultiple { Count = count, Data = results }; return OpResult>.Ok(result); }); } /// /// Get all DB object matching the predicate built from keys /// /// The page numeber (0 based) /// The maximum number of items par page /// The order by function /// The key names and values /// All matching objects public static OpResult> GetMultipleByKeys(Expression> orderBy, int page = 0, int perPage = Int32.MaxValue, params KeyValuePair[] keys) { return GetMultiple(GetExpression(keys), orderBy, page, perPage); } /// /// Add an entry in the database /// /// The object to be added /// Used to return some data /// The result defined by returnFunc public static OpResult Add(TDboAdd obj, Expression> returnFunc) { return Execute((db, table) => { var add = table.Create(); var item = DboAddToDbStatic(obj, add); if (!item) return item.To(); table.Add(add); db.SaveChanges(); var res = returnFunc.Compile().DynamicInvoke(add); return OpResult.Ok((T)res); }); } /// /// Add an entry in the database /// /// The object to be added /// Always true or an OpResult error public static OpResult Add(TDboAdd obj) { return Add(obj, x => true); } /// /// Add an entry in the database /// /// The object to be added /// The DBO or an OpResult error public static OpResult AddDbo(TDboAdd obj) { return Add(obj, x => DbToDboGetStatic(x)); } /// /// Add an entry in the database /// /// The object to be added /// The DBO or an OpResult error public static OpResult AddId(TDboAdd obj) { var param = Expression.Parameter(typeof(TDbObject), "x"); var exp = Expression.Property(param, "id"); var lambda = Expression.Lambda>(exp, param); return Add(obj, lambda); } /// /// Edit an entry in the database /// /// The object to be added /// The predicate to be used to select data /// Always true or an OpResult error public static OpResult Edit(TDboEdit obj, Expression> predicate) { return Execute((db, table) => { var edit = GetSingleDbObject(table, predicate); if (!edit) return edit.To(); var res = DboEditToDbStatic(obj, edit.Data); if (!res) return res.To(); db.Entry(edit.Data).CurrentValues.SetValues(edit.Data); db.SaveChanges(); return OpResult.Ok(true); }); } /// /// Edit an entry in the database /// /// The object to be added /// The keys to be used to select data /// Always true or an OpResult error public static OpResult Edit(TDboEdit obj, params KeyValuePair[] keys) { return Edit(obj, GetExpression(keys)); } /// /// Edit an entry in the database /// /// The object to be added /// The id to be edited /// Always true or an OpResult error public static OpResult EditById(TDboEdit obj, long id) { return Edit(obj, new KeyValuePair("id", id)); } /// /// Delete an entry in the database /// /// The predicate to be used to delete data /// Always true or an OpResult error public static OpResult Delete(Expression> predicate) { return Execute((db, table) => { var del = GetSingleDbObject(table, predicate); if (!del) return del.To(); table.Remove(del.Data); db.SaveChanges(); return OpResult.Ok(true); }); } /// /// Delete an entry in the database /// /// The keys to be used to delete data /// Always true or an OpResult error public static OpResult Delete(params KeyValuePair[] keys) { return Delete(GetExpression(keys)); } /// /// Delete an entry in the database /// /// The id to be deleted /// Always true or an OpResult error public static OpResult DeleteById(long id) { return Delete(new KeyValuePair("id", id)); } } }