Client.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using System.Timers;
  6. using InABox.Core;
  7. namespace InABox.Clients
  8. {
  9. public enum SerializerProtocol
  10. {
  11. Rest
  12. }
  13. public class QueryMultipleResults
  14. {
  15. private readonly Dictionary<string, CoreTable> Results;
  16. internal QueryMultipleResults(Dictionary<string, CoreTable> results)
  17. {
  18. Results = results;
  19. }
  20. public CoreTable this[string name] => Results[name];
  21. public CoreTable Get<T>() => Results[typeof(T).Name];
  22. public CoreTable Get(string name) => Results[name];
  23. }
  24. public abstract class Client
  25. {
  26. public abstract CoreTable Query(IFilter? filter = null, IColumns? columns = null, ISortOrder? sortOrder = null);
  27. public abstract void Save(Entity entity, string auditNote);
  28. private static IClient CheckClient()
  29. {
  30. using (new Profiler(true))
  31. return ClientFactory.CreateClient<User>();
  32. }
  33. public static Dictionary<string, CoreTable> QueryMultiple(Dictionary<string, IQueryDef> queries)
  34. {
  35. try
  36. {
  37. using var timer = new Profiler(false);
  38. var result = CheckClient().QueryMultiple(queries);
  39. timer.Log(result.Sum(x => x.Value.Rows.Count));
  40. return result;
  41. }
  42. catch (RequestException e)
  43. {
  44. ClientFactory.RaiseRequestError(e);
  45. throw;
  46. }
  47. }
  48. public static QueryMultipleResults QueryMultiple(params IKeyedQueryDef[] queries)
  49. {
  50. try
  51. {
  52. using var timer = new Profiler(false);
  53. var result = CheckClient().QueryMultiple(queries.ToDictionary(x => x.Key, x => x as IQueryDef));
  54. timer.Log(result.Sum(x => x.Value.Rows.Count));
  55. return new QueryMultipleResults(result);
  56. }
  57. catch (RequestException e)
  58. {
  59. ClientFactory.RaiseRequestError(e);
  60. throw;
  61. }
  62. }
  63. public static QueryMultipleResults QueryMultiple(IEnumerable<IKeyedQueryDef> queries)
  64. {
  65. try
  66. {
  67. using var timer = new Profiler(false);
  68. var result = CheckClient().QueryMultiple(queries.ToDictionary(x => x.Key, x => x as IQueryDef));
  69. timer.Log(result.Sum(x => x.Value.Rows.Count));
  70. return new QueryMultipleResults(result);
  71. }
  72. catch (RequestException e)
  73. {
  74. ClientFactory.RaiseRequestError(e);
  75. throw;
  76. }
  77. }
  78. public static ValidationData Validate(Guid session)
  79. {
  80. try
  81. {
  82. using (new Profiler(true))
  83. return CheckClient().Validate(session);
  84. }
  85. catch (RequestException e)
  86. {
  87. ClientFactory.RaiseRequestError(e);
  88. throw;
  89. }
  90. }
  91. public static ValidationData Validate(string pin, Guid session = default)
  92. {
  93. try
  94. {
  95. using (new Profiler(true))
  96. return CheckClient().Validate(pin, session);
  97. }
  98. catch (RequestException e)
  99. {
  100. ClientFactory.RaiseRequestError(e);
  101. throw;
  102. }
  103. }
  104. public static ValidationData Validate(string userid, string password, Guid session = default)
  105. {
  106. try
  107. {
  108. using (new Profiler(true))
  109. return CheckClient().Validate(userid, password, session);
  110. }
  111. catch (RequestException e)
  112. {
  113. ClientFactory.RaiseRequestError(e);
  114. throw;
  115. }
  116. }
  117. public static bool Check2FA(string code, Guid? session = null)
  118. {
  119. try
  120. {
  121. using (new Profiler(true))
  122. return CheckClient().Check2FA(code, session);
  123. }
  124. catch (RequestException e)
  125. {
  126. ClientFactory.RaiseRequestError(e);
  127. throw;
  128. }
  129. }
  130. public static bool Ping()
  131. {
  132. try
  133. {
  134. using (new Profiler(true))
  135. return CheckClient().Ping();
  136. }
  137. catch (RequestException e)
  138. {
  139. ClientFactory.RaiseRequestError(e);
  140. throw;
  141. }
  142. }
  143. public static DatabaseInfo Info()
  144. {
  145. try
  146. {
  147. using (new Profiler(true))
  148. return CheckClient().Info();
  149. }
  150. catch (RequestException e)
  151. {
  152. ClientFactory.RaiseRequestError(e);
  153. throw;
  154. }
  155. }
  156. public static Client Create(Type TEntity) =>
  157. (Activator.CreateInstance(typeof(Client<>).MakeGenericType(TEntity)) as Client)!;
  158. }
  159. public class Client<TEntity> : Client, IDisposable where TEntity : Entity, IPersistent, IRemotable, new()
  160. {
  161. private IClient<TEntity> _client;
  162. public Client()
  163. {
  164. _client = ClientFactory.CreateClient<TEntity>();
  165. }
  166. public void Dispose()
  167. {
  168. }
  169. private void CheckSupported()
  170. {
  171. if (!ClientFactory.IsSupported<TEntity>())
  172. throw new NotSupportedException(string.Format("{0} is not supported in this context", typeof(TEntity).EntityName()));
  173. }
  174. private string FilterToString(Filter<TEntity> filter)
  175. {
  176. return filter != null ? filter.AsOData() : "";
  177. }
  178. private string OrderToString(SortOrder<TEntity> order)
  179. {
  180. return order != null ? order.AsOData() : "";
  181. }
  182. public CoreTable Query(Filter<TEntity>? filter = null, Columns<TEntity>? columns = null, SortOrder<TEntity>? orderby = null)
  183. {
  184. try
  185. {
  186. using (var timer = new Profiler<TEntity>(false))
  187. {
  188. CheckSupported();
  189. var result = _client.Query(filter, columns, orderby);
  190. timer.Log(result.Rows.Count);
  191. return result;
  192. }
  193. }
  194. catch(RequestException e)
  195. {
  196. ClientFactory.RaiseRequestError(e);
  197. throw;
  198. }
  199. }
  200. public override CoreTable Query(IFilter? filter, IColumns? columns, ISortOrder? sortOrder)
  201. {
  202. return Query(filter as Filter<TEntity>, columns as Columns<TEntity>, sortOrder as SortOrder<TEntity>);
  203. }
  204. public void Query(Filter<TEntity>? filter, Columns<TEntity>? columns, SortOrder<TEntity>? sort, Action<CoreTable?, Exception?> callback)
  205. {
  206. try
  207. {
  208. var timer = new Profiler<TEntity>(false);
  209. CheckSupported();
  210. _client.Query(filter, columns, sort, (c, e) =>
  211. {
  212. timer.Dispose(c != null ? c.Rows.Count : -1);
  213. callback?.Invoke(c, e);
  214. });
  215. }
  216. catch (RequestException e)
  217. {
  218. ClientFactory.RaiseRequestError(e);
  219. throw;
  220. }
  221. }
  222. public TEntity[] Load(Filter<TEntity>? filter = null, SortOrder<TEntity>? sort = null)
  223. {
  224. try
  225. {
  226. using (var timer = new Profiler<TEntity>(false))
  227. {
  228. CheckSupported();
  229. var result = _client.Load(filter, sort);
  230. foreach (var entity in result)
  231. entity.CommitChanges();
  232. timer.Log(result.Length);
  233. return result;
  234. }
  235. }
  236. catch (RequestException e)
  237. {
  238. ClientFactory.RaiseRequestError(e);
  239. throw;
  240. }
  241. }
  242. public void Load(Filter<TEntity> filter, SortOrder<TEntity> sort, Action<TEntity[]?, Exception?> callback)
  243. {
  244. try
  245. {
  246. var timer = new Profiler<TEntity>(false);
  247. CheckSupported();
  248. _client.Load(filter, sort, (i, e) =>
  249. {
  250. timer.Dispose(i != null ? i.Length : -1);
  251. callback?.Invoke(i, e);
  252. });
  253. }
  254. catch (RequestException e)
  255. {
  256. ClientFactory.RaiseRequestError(e);
  257. throw;
  258. }
  259. }
  260. public override void Save(Entity entity, string auditNote)
  261. {
  262. try
  263. {
  264. Save((entity as TEntity)!, auditNote);
  265. }
  266. catch (RequestException e)
  267. {
  268. ClientFactory.RaiseRequestError(e);
  269. throw;
  270. }
  271. }
  272. public void Save(TEntity entity, string auditnote)
  273. {
  274. try
  275. {
  276. using (new Profiler<TEntity>(true))
  277. {
  278. CheckSupported();
  279. entity.LastUpdate = DateTime.Now;
  280. entity.LastUpdateBy = ClientFactory.UserID;
  281. _client.Save(entity, auditnote);
  282. entity.CommitChanges();
  283. }
  284. }
  285. catch (RequestException e)
  286. {
  287. ClientFactory.RaiseRequestError(e);
  288. throw;
  289. }
  290. }
  291. public void Save(TEntity entity, string auditnote, Action<TEntity, Exception?> callback)
  292. {
  293. try
  294. {
  295. var timer = new Profiler<TEntity>(false);
  296. CheckSupported();
  297. _client.Save(entity, auditnote, (i, c) =>
  298. {
  299. timer.Dispose();
  300. callback?.Invoke(i, c);
  301. });
  302. }
  303. catch (RequestException e)
  304. {
  305. ClientFactory.RaiseRequestError(e);
  306. throw;
  307. }
  308. }
  309. public void Save(IEnumerable<TEntity> entities, string auditnote)
  310. {
  311. try
  312. {
  313. using var timer = new Profiler<TEntity>(false);
  314. CheckSupported();
  315. if (entities.Any())
  316. _client.Save(entities, auditnote);
  317. timer.Log(entities.Count());
  318. }
  319. catch (RequestException e)
  320. {
  321. ClientFactory.RaiseRequestError(e);
  322. throw;
  323. }
  324. }
  325. public void Save(IEnumerable<TEntity> entities, string auditnote, Action<IEnumerable<TEntity>, Exception?> callback)
  326. {
  327. try
  328. {
  329. var timer = new Profiler<TEntity>(false);
  330. CheckSupported();
  331. if (entities.Any())
  332. _client.Save(entities, auditnote, (i, e) =>
  333. {
  334. timer.Dispose(i.Count());
  335. callback?.Invoke(i, e);
  336. });
  337. }
  338. catch (RequestException e)
  339. {
  340. ClientFactory.RaiseRequestError(e);
  341. throw;
  342. }
  343. }
  344. public void Delete(TEntity entity, string auditnote)
  345. {
  346. try
  347. {
  348. using (new Profiler<TEntity>(true))
  349. {
  350. CheckSupported();
  351. _client.Delete(entity, auditnote);
  352. }
  353. }
  354. catch (RequestException e)
  355. {
  356. ClientFactory.RaiseRequestError(e);
  357. throw;
  358. }
  359. }
  360. public void Delete(TEntity entity, string auditnote, Action<TEntity, Exception?> callback)
  361. {
  362. try
  363. {
  364. var timer = new Profiler<TEntity>(true);
  365. CheckSupported();
  366. _client.Delete(entity, auditnote, (i, e) =>
  367. {
  368. timer.Dispose();
  369. callback?.Invoke(i, e);
  370. });
  371. }
  372. catch (RequestException e)
  373. {
  374. ClientFactory.RaiseRequestError(e);
  375. throw;
  376. }
  377. }
  378. public void Delete(IList<TEntity> entities, string auditnote)
  379. {
  380. try
  381. {
  382. using var timer = new Profiler<TEntity>(false);
  383. CheckSupported();
  384. _client.Delete(entities, auditnote);
  385. timer.Log(entities.Count());
  386. }
  387. catch (RequestException e)
  388. {
  389. ClientFactory.RaiseRequestError(e);
  390. throw;
  391. }
  392. }
  393. public void Delete(IList<TEntity> entities, string auditnote, Action<IList<TEntity>, Exception?> callback)
  394. {
  395. try
  396. {
  397. var timer = new Profiler<TEntity>(false);
  398. CheckSupported();
  399. _client.Delete(entities, auditnote, (i, e) =>
  400. {
  401. timer.Dispose(entities.Count());
  402. callback?.Invoke(i, e);
  403. });
  404. }
  405. catch (RequestException e)
  406. {
  407. ClientFactory.RaiseRequestError(e);
  408. throw;
  409. }
  410. }
  411. public IEnumerable<string> SupportedTypes()
  412. {
  413. try
  414. {
  415. using (new Profiler(true))
  416. return _client.SupportedTypes();
  417. }
  418. catch (RequestException e)
  419. {
  420. ClientFactory.RaiseRequestError(e);
  421. throw;
  422. }
  423. }
  424. public new DatabaseInfo Info()
  425. {
  426. try
  427. {
  428. using (new Profiler(true))
  429. return _client.Info();
  430. }
  431. catch (RequestException e)
  432. {
  433. ClientFactory.RaiseRequestError(e);
  434. throw;
  435. }
  436. }
  437. }
  438. }