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 13KB

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