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.

SqlServerManager.cs 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Entity;
  4. using System.Linq;
  5. using System.Linq.Expressions;
  6. using System.Runtime.Serialization;
  7. using iiie.Logs.DBO;
  8. using iiie.WebApiUtils.DBO;
  9. namespace iiie.WebApiUtils.BusinessManager
  10. {
  11. /// <summary>
  12. /// Helper for SQL Server data access
  13. /// </summary>
  14. public abstract class SqlServerManager<TDbObject, TDboGet, TDboAdd, TDboEdit, TEntities, TThis>
  15. : SqlServerBasicManager<TDbObject, TEntities, TThis>
  16. where TDbObject : class
  17. where TEntities : DbContext, new()
  18. where TThis : SqlServerManager<TDbObject, TDboGet, TDboAdd, TDboEdit, TEntities, TThis>, new()
  19. {
  20. /// <summary>
  21. /// Convert a DB object to DBO
  22. /// </summary>
  23. /// <param name="obj">The object to be converted</param>
  24. /// <returns>The DBO</returns>
  25. public abstract TDboGet DbToDboGet(TDbObject obj);
  26. /// <summary>
  27. /// Convert a DBO to DB object
  28. /// </summary>
  29. /// <param name="obj">The object to be converted</param>
  30. /// <returns>The DB object</returns>
  31. public abstract OpResult<TDbObject> DboAddToDb(TDboAdd obj);
  32. /// <summary>
  33. /// Return a global predicate that will be applied to all selects
  34. /// </summary>
  35. /// <returns>The expression</returns>
  36. public virtual Expression<Func<TDbObject, bool>> GetGlobalSelectPredicate()
  37. {
  38. return x => true;
  39. }
  40. /// <summary>
  41. /// Convert a DBO to DB object
  42. /// </summary>
  43. /// <param name="obj">The object to be converted</param>
  44. /// <param name="edit">The object beeing edited</param>
  45. /// <returns>The DB object</returns>
  46. public abstract OpResult<TDbObject> DboEditToDb(TDboEdit obj, TDbObject edit);
  47. /// <summary>
  48. /// Helper to get real select predicate
  49. /// </summary>
  50. /// <returns>The global predicate</returns>
  51. public static Expression<Func<TDbObject, bool>> GetGlobalSelectPredicateStatic()
  52. {
  53. var obj = new TThis();
  54. return obj.GetGlobalSelectPredicate();
  55. }
  56. /// <summary>
  57. /// Helper to convert DB object to DBO
  58. /// </summary>
  59. /// <param name="res">The result to convert</param>
  60. /// <returns>The DBO object</returns>
  61. public static TDboGet DbToDboGetStatic(TDbObject res)
  62. {
  63. var obj = new TThis();
  64. return obj.DbToDboGet(res);
  65. }
  66. /// <summary>
  67. /// Helper to convert DBO object to DB
  68. /// </summary>
  69. /// <param name="res">The result to convert</param>
  70. /// <returns>The DB object</returns>
  71. public static OpResult<TDbObject> DboAddToDbStatic(TDboAdd res)
  72. {
  73. var obj = new TThis();
  74. return obj.DboAddToDb(res);
  75. }
  76. /// <summary>
  77. /// Helper to convert DBO object to DB
  78. /// </summary>
  79. /// <param name="res">The result to convert</param>
  80. /// <param name="edit">The object beeing edited</param>
  81. /// <returns>The DB object</returns>
  82. public static OpResult<TDbObject> DboEditToDbStatic(TDboEdit res, TDbObject edit)
  83. {
  84. var obj = new TThis();
  85. return obj.DboEditToDb(res, edit);
  86. }
  87. /// <summary>
  88. /// Get a single DB object matching the predicate
  89. /// </summary>
  90. /// <param name="table">The table to search in</param>
  91. /// <param name="predicate">The predicate</param>
  92. /// <returns>The object that match</returns>
  93. public static OpResult<TDbObject> GetSingleDbObject(DbSet<TDbObject> table, Expression<Func<TDbObject, bool>> predicate)
  94. {
  95. var o = table.Where(GetGlobalSelectPredicateStatic()).FirstOrDefault(predicate);
  96. if (o == null)
  97. {
  98. return OpResult<TDbObject>.Error(ResultStatus.NotFound, typeof(TThis).Name + ": Value not found", "");
  99. }
  100. return OpResult<TDbObject>.Ok(o);
  101. }
  102. /// <summary>
  103. /// Get a single DBO matching the predicate
  104. /// </summary>
  105. /// <param name="predicate">The predicate</param>
  106. /// <returns>The object that match, or null</returns>
  107. public static OpResult<TDboGet> GetSingle(Expression<Func<TDbObject, bool>> predicate)
  108. {
  109. return Execute((db, table) =>
  110. {
  111. var obj = GetSingleDbObject(table, predicate);
  112. if (!obj)
  113. return obj.To<TDboGet>();
  114. return OpResult<TDboGet>.Ok(DbToDboGetStatic(obj.Data));
  115. });
  116. }
  117. /// <summary>
  118. /// Get an object by its primary key(s)
  119. /// </summary>
  120. /// <param name="keys">The key names and values</param>
  121. /// <returns>The object</returns>
  122. public static OpResult<TDboGet> GetSingleByKeys(params KeyValuePair<string, object>[] keys)
  123. {
  124. return GetSingle(GetExpression(keys));
  125. }
  126. /// <summary>
  127. /// Get an object by its id
  128. /// </summary>
  129. /// <param name="id">The id of the object</param>
  130. /// <returns>The object</returns>
  131. public static OpResult<TDboGet> GetSingleById(long id)
  132. {
  133. return GetSingleByKeys(new KeyValuePair<string, object>("id", id));
  134. }
  135. /// <summary>
  136. /// Get all DB object matching the predicate
  137. /// </summary>
  138. /// <param name="predicate">The predicate</param>
  139. /// <param name="orderBy">The order by function</param>
  140. /// <param name="page">The page numeber (0 based)</param>
  141. /// <param name="perPage">The maximum number of items par page</param>
  142. /// <returns>All matching objects</returns>
  143. public static OpResult<DboGetMultiple<TDboGet>> GetMultiple<TKey>(Expression<Func<TDbObject, bool>> predicate,
  144. Expression<Func<TDbObject, TKey>> orderBy, int page = 0, int perPage = Int32.MaxValue)
  145. {
  146. return Execute((db, table) =>
  147. {
  148. var globalPredicate = GetGlobalSelectPredicateStatic();
  149. var count = table.Where(globalPredicate).Count(predicate);
  150. var results = table.OrderBy(orderBy).Where(globalPredicate).Where(predicate)
  151. .Skip(page * perPage).Take(perPage).Select(DbToDboGetStatic).ToList();
  152. var result = new DboGetMultiple<TDboGet>
  153. {
  154. Count = count,
  155. Data = results
  156. };
  157. return OpResult<DboGetMultiple<TDboGet>>.Ok(result);
  158. });
  159. }
  160. /// <summary>
  161. /// Get all DB object matching the predicate built from keys
  162. /// </summary>
  163. /// <param name="page">The page numeber (0 based)</param>
  164. /// <param name="perPage">The maximum number of items par page</param>
  165. /// <param name="orderBy">The order by function</param>
  166. /// <param name="keys">The key names and values</param>
  167. /// <returns>All matching objects</returns>
  168. public static OpResult<DboGetMultiple<TDboGet>> GetMultipleByKeys<TKey>(Expression<Func<TDbObject, TKey>> orderBy,
  169. int page = 0, int perPage = Int32.MaxValue, params KeyValuePair<string, object>[] keys)
  170. {
  171. return GetMultiple(GetExpression(keys), orderBy, page, perPage);
  172. }
  173. /// <summary>
  174. /// Add an entry in the database
  175. /// </summary>
  176. /// <param name="obj">The object to be added</param>
  177. /// <param name="returnFunc">Used to return some data</param>
  178. /// <returns>The result defined by returnFunc</returns>
  179. public static OpResult<T> Add<T>(TDboAdd obj, Expression<Func<TDbObject, T>> returnFunc)
  180. {
  181. return Execute((db, table) =>
  182. {
  183. var item = DboAddToDbStatic(obj);
  184. if (!item)
  185. return item.To<T>();
  186. table.Add(item.Data);
  187. db.SaveChanges();
  188. var res = returnFunc.Compile().DynamicInvoke(item.Data);
  189. return OpResult<T>.Ok((T)res);
  190. });
  191. }
  192. /// <summary>
  193. /// Add an entry in the database
  194. /// </summary>
  195. /// <param name="obj">The object to be added</param>
  196. /// <returns>Always true or an OpResult error</returns>
  197. public static OpResult<bool> Add(TDboAdd obj)
  198. {
  199. return Add(obj, x => true);
  200. }
  201. /// <summary>
  202. /// Add an entry in the database
  203. /// </summary>
  204. /// <param name="obj">The object to be added</param>
  205. /// <returns>The DBO or an OpResult error</returns>
  206. public static OpResult<TDboGet> AddDbo(TDboAdd obj)
  207. {
  208. return Add(obj, x => DbToDboGetStatic(x));
  209. }
  210. /// <summary>
  211. /// Add an entry in the database
  212. /// </summary>
  213. /// <param name="obj">The object to be added</param>
  214. /// <returns>The DBO or an OpResult error</returns>
  215. public static OpResult<long> AddId(TDboAdd obj)
  216. {
  217. var param = Expression.Parameter(typeof(TDbObject), "x");
  218. var exp = Expression.Property(param, "id");
  219. var lambda = Expression.Lambda<Func<TDbObject, long>>(exp, param);
  220. return Add(obj, lambda);
  221. }
  222. /// <summary>
  223. /// Edit an entry in the database
  224. /// </summary>
  225. /// <param name="obj">The object to be added</param>
  226. /// <param name="predicate">The predicate to be used to select data</param>
  227. /// <returns>Always true or an OpResult error</returns>
  228. public static OpResult<bool> Edit(TDboEdit obj, Expression<Func<TDbObject, bool>> predicate)
  229. {
  230. return Execute((db, table) =>
  231. {
  232. var edit = GetSingleDbObject(table, predicate);
  233. if (!edit)
  234. return edit.To<bool>();
  235. var res = DboEditToDbStatic(obj, edit.Data);
  236. if (!res)
  237. return res.To<bool>();
  238. db.Entry(edit.Data).CurrentValues.SetValues(res.Data);
  239. db.SaveChanges();
  240. return OpResult<bool>.Ok(true);
  241. });
  242. }
  243. /// <summary>
  244. /// Edit an entry in the database
  245. /// </summary>
  246. /// <param name="obj">The object to be added</param>
  247. /// <param name="keys">The keys to be used to select data</param>
  248. /// <returns>Always true or an OpResult error</returns>
  249. public static OpResult<bool> Edit(TDboEdit obj, params KeyValuePair<string, object>[] keys)
  250. {
  251. return Edit(obj, GetExpression(keys));
  252. }
  253. /// <summary>
  254. /// Edit an entry in the database
  255. /// </summary>
  256. /// <param name="obj">The object to be added</param>
  257. /// <param name="id">The id to be edited</param>
  258. /// <returns>Always true or an OpResult error</returns>
  259. public static OpResult<bool> EditById(TDboEdit obj, long id)
  260. {
  261. return Edit(obj, new KeyValuePair<string, object>("id", id));
  262. }
  263. /// <summary>
  264. /// Delete an entry in the database
  265. /// </summary>
  266. /// <param name="predicate">The predicate to be used to delete data</param>
  267. /// <returns>Always true or an OpResult error</returns>
  268. public static OpResult<bool> Delete(Expression<Func<TDbObject, bool>> predicate)
  269. {
  270. return Execute((db, table) =>
  271. {
  272. var del = GetSingleDbObject(table, predicate);
  273. if (!del)
  274. return del.To<bool>();
  275. table.Remove(del.Data);
  276. db.SaveChanges();
  277. return OpResult<bool>.Ok(true);
  278. });
  279. }
  280. /// <summary>
  281. /// Delete an entry in the database
  282. /// </summary>
  283. /// <param name="keys">The keys to be used to delete data</param>
  284. /// <returns>Always true or an OpResult error</returns>
  285. public static OpResult<bool> Delete(params KeyValuePair<string, object>[] keys)
  286. {
  287. return Delete(GetExpression(keys));
  288. }
  289. /// <summary>
  290. /// Delete an entry in the database
  291. /// </summary>
  292. /// <param name="id">The id to be deleted</param>
  293. /// <returns>Always true or an OpResult error</returns>
  294. public static OpResult<bool> DeleteById(long id)
  295. {
  296. return Delete(new KeyValuePair<string, object>("id", id));
  297. }
  298. }
  299. }