MultiQuery.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading.Tasks;
  5. using InABox.Clients;
  6. namespace InABox.Core
  7. {
  8. public class MultiQuery
  9. {
  10. private readonly List<InternalQueryDef> _queries = new List<InternalQueryDef>();
  11. public int Count => _queries.Count;
  12. public Dictionary<object, IQueryDef> Definitions()
  13. {
  14. Dictionary<object, IQueryDef> result = new Dictionary<object, IQueryDef>();
  15. foreach (var query in _queries)
  16. result[query.Key] = query.Query;
  17. return result;
  18. }
  19. public void Clear()
  20. {
  21. _queries.Clear();
  22. }
  23. public void Add(IQueryDef query, object key)
  24. {
  25. if (key == null)
  26. throw new Exception("MultiQuery Key many not be null");
  27. if (_queries.Any(x => Equals(x.Key, key)))
  28. throw new Exception("Key already exists");
  29. _queries.Add(new InternalQueryDef
  30. {
  31. Key = key,
  32. Query = query
  33. });
  34. }
  35. public void Query(Action<MultiQuery> callback = null)
  36. {
  37. var tasks = new Dictionary<Task<CoreTable>, object>();
  38. foreach (var query in _queries)
  39. {
  40. var task = Task.Run(
  41. () =>
  42. {
  43. var client = ClientFactory.CreateClient(query.Query.Type);
  44. return client.Query(query.Query.Filter, query.Query.Columns, query.Query.SortOrder);
  45. }
  46. );
  47. tasks[task] = query.Key;
  48. }
  49. if (callback == null)
  50. {
  51. Task.WaitAll(tasks.Keys.ToArray());
  52. foreach (var task in tasks.Keys)
  53. {
  54. var query = _queries.FirstOrDefault(x => Equals(x.Key, tasks[task]));
  55. query.Result = task.Result;
  56. }
  57. }
  58. else
  59. {
  60. Task.WhenAll(tasks.Keys.ToArray()).ContinueWith(t =>
  61. {
  62. foreach (var task in tasks.Keys)
  63. {
  64. var query = _queries.FirstOrDefault(x => Equals(x.Key, tasks[task]));
  65. query.Result = task.Result;
  66. }
  67. callback.Invoke(this);
  68. });
  69. }
  70. }
  71. public bool Contains(object key)
  72. {
  73. return _queries.Any(x => Equals(x.Key, key));
  74. }
  75. public CoreTable Get(object key)
  76. {
  77. var query = _queries.FirstOrDefault(x => Equals(x.Key, key));
  78. if (query == null)
  79. throw new Exception("Key does not exist");
  80. if (query.Result == null)
  81. throw new Exception("No result available");
  82. return query.Result;
  83. }
  84. public void Set(object key, CoreTable table)
  85. {
  86. var query = _queries.FirstOrDefault(x => Equals(x.Key, key));
  87. if (query == null)
  88. throw new Exception("Key does not exist");
  89. query.Result = table;
  90. }
  91. private class InternalQueryDef
  92. {
  93. public object Key { get; set; }
  94. public IQueryDef Query { get; set; }
  95. public CoreTable Result { get; set; }
  96. public Entity[] Updates { get; set; }
  97. }
  98. #region Simplified Generic Helpers
  99. public void Add<T>(Filter<T> filter = null, Columns<T> columns = null, SortOrder<T> sort = null)
  100. where T : Entity, IRemotable, IPersistent, new()
  101. {
  102. Add(new QueryDef<T>(filter, columns, sort), typeof(T));
  103. }
  104. public CoreTable Get<T>()
  105. {
  106. return Get(typeof(T));
  107. }
  108. public bool Contains<T>()
  109. {
  110. return Contains(typeof(T));
  111. }
  112. #endregion
  113. }
  114. }