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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  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 count = table.Count(predicate);
  149. var results = table.OrderBy(orderBy).Where(GetGlobalSelectPredicateStatic())
  150. .Where(predicate).Skip(page * perPage).Take(perPage).Select(DbToDboGetStatic).ToList();
  151. var result = new DboGetMultiple<TDboGet>
  152. {
  153. Count = count,
  154. Data = results
  155. };
  156. return OpResult<DboGetMultiple<TDboGet>>.Ok(result);
  157. });
  158. }
  159. /// <summary>
  160. /// Get all DB object matching the predicate built from keys
  161. /// </summary>
  162. /// <param name="page">The page numeber (0 based)</param>
  163. /// <param name="perPage">The maximum number of items par page</param>
  164. /// <param name="orderBy">The order by function</param>
  165. /// <param name="keys">The key names and values</param>
  166. /// <returns>All matching objects</returns>
  167. public static OpResult<DboGetMultiple<TDboGet>> GetMultipleByKeys<TKey>(Expression<Func<TDbObject, TKey>> orderBy,
  168. int page = 0, int perPage = Int32.MaxValue, params KeyValuePair<string, object>[] keys)
  169. {
  170. return GetMultiple(GetExpression(keys), orderBy, page, perPage);
  171. }
  172. /// <summary>
  173. /// Add an entry in the database
  174. /// </summary>
  175. /// <param name="obj">The object to be added</param>
  176. /// <param name="returnFunc">Used to return some data</param>
  177. /// <returns>The result defined by returnFunc</returns>
  178. public static OpResult<T> Add<T>(TDboAdd obj, Expression<Func<TDbObject, T>> returnFunc)
  179. {
  180. return Execute((db, table) =>
  181. {
  182. var item = DboAddToDbStatic(obj);
  183. if (!item)
  184. return item.To<T>();
  185. table.Add(item.Data);
  186. db.SaveChanges();
  187. var res = returnFunc.Compile().DynamicInvoke(item.Data);
  188. return OpResult<T>.Ok((T)res);
  189. });
  190. }
  191. /// <summary>
  192. /// Add an entry in the database
  193. /// </summary>
  194. /// <param name="obj">The object to be added</param>
  195. /// <returns>Always true or an OpResult error</returns>
  196. public static OpResult<bool> Add(TDboAdd obj)
  197. {
  198. return Add(obj, x => true);
  199. }
  200. /// <summary>
  201. /// Add an entry in the database
  202. /// </summary>
  203. /// <param name="obj">The object to be added</param>
  204. /// <returns>The DBO or an OpResult error</returns>
  205. public static OpResult<TDboGet> AddDbo(TDboAdd obj)
  206. {
  207. return Add(obj, x => DbToDboGetStatic(x));
  208. }
  209. /// <summary>
  210. /// Add an entry in the database
  211. /// </summary>
  212. /// <param name="obj">The object to be added</param>
  213. /// <returns>The DBO or an OpResult error</returns>
  214. public static OpResult<long> AddId(TDboAdd obj)
  215. {
  216. var param = Expression.Parameter(typeof(TDbObject), "x");
  217. var exp = Expression.Property(param, "id");
  218. var lambda = Expression.Lambda<Func<TDbObject, long>>(exp, param);
  219. return Add(obj, lambda);
  220. }
  221. /// <summary>
  222. /// Edit an entry in the database
  223. /// </summary>
  224. /// <param name="obj">The object to be added</param>
  225. /// <param name="predicate">The predicate to be used to select data</param>
  226. /// <returns>Always true or an OpResult error</returns>
  227. public static OpResult<bool> Edit(TDboEdit obj, Expression<Func<TDbObject, bool>> predicate)
  228. {
  229. return Execute((db, table) =>
  230. {
  231. var edit = GetSingleDbObject(table, predicate);
  232. if (!edit)
  233. return edit.To<bool>();
  234. var res = DboEditToDbStatic(obj, edit.Data);
  235. if (!res)
  236. return res.To<bool>();
  237. db.Entry(edit.Data).CurrentValues.SetValues(res.Data);
  238. db.SaveChanges();
  239. return OpResult<bool>.Ok(true);
  240. });
  241. }
  242. /// <summary>
  243. /// Edit an entry in the database
  244. /// </summary>
  245. /// <param name="obj">The object to be added</param>
  246. /// <param name="keys">The keys to be used to select data</param>
  247. /// <returns>Always true or an OpResult error</returns>
  248. public static OpResult<bool> Edit(TDboEdit obj, params KeyValuePair<string, object>[] keys)
  249. {
  250. return Edit(obj, GetExpression(keys));
  251. }
  252. /// <summary>
  253. /// Edit an entry in the database
  254. /// </summary>
  255. /// <param name="obj">The object to be added</param>
  256. /// <param name="id">The id to be edited</param>
  257. /// <returns>Always true or an OpResult error</returns>
  258. public static OpResult<bool> EditById(TDboEdit obj, long id)
  259. {
  260. return Edit(obj, new KeyValuePair<string, object>("id", id));
  261. }
  262. /// <summary>
  263. /// Delete an entry in the database
  264. /// </summary>
  265. /// <param name="predicate">The predicate to be used to delete data</param>
  266. /// <returns>Always true or an OpResult error</returns>
  267. public static OpResult<bool> Delete(Expression<Func<TDbObject, bool>> predicate)
  268. {
  269. return Execute((db, table) =>
  270. {
  271. var del = GetSingleDbObject(table, predicate);
  272. if (!del)
  273. return del.To<bool>();
  274. table.Remove(del.Data);
  275. db.SaveChanges();
  276. return OpResult<bool>.Ok(true);
  277. });
  278. }
  279. /// <summary>
  280. /// Delete an entry in the database
  281. /// </summary>
  282. /// <param name="keys">The keys to be used to delete data</param>
  283. /// <returns>Always true or an OpResult error</returns>
  284. public static OpResult<bool> Delete(params KeyValuePair<string, object>[] keys)
  285. {
  286. return Delete(GetExpression(keys));
  287. }
  288. /// <summary>
  289. /// Delete an entry in the database
  290. /// </summary>
  291. /// <param name="id">The id to be deleted</param>
  292. /// <returns>Always true or an OpResult error</returns>
  293. public static OpResult<bool> DeleteById(long id)
  294. {
  295. return Delete(new KeyValuePair<string, object>("id", id));
  296. }
  297. }
  298. }