diff --git a/commercetools.Sdk/commercetools.Sdk.Client/ClientQueryAllEnumerator.cs b/commercetools.Sdk/commercetools.Sdk.Client/ClientQueryAllEnumerator.cs new file mode 100644 index 00000000..af1aa6ff --- /dev/null +++ b/commercetools.Sdk/commercetools.Sdk.Client/ClientQueryAllEnumerator.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using commercetools.Sdk.Domain; + +namespace commercetools.Sdk.Client +{ + public class ClientQueryAllEnumerator : IEnumerator + { + private const int DefaultOffset = 0; + private const int DefaultLimit = 20; + + private IClient client; + private QueryCommand command; + + private List resultSet; + private int position = -1; + + public ClientQueryAllEnumerator(IClient client, QueryCommand command) + { + if (client == null) + { + throw new FieldAccessException("Client cannot be null"); + } + + this.client = client; + this.command = command; + } + + public bool MoveNext() + { + this.position++; + if (this.command.QueryParameters is IPageable pageableParameters && pageableParameters.Limit == null) + { + var limit = DefaultLimit; + if (this.resultSet == null || this.position % limit == 0) + { + // Retrieve new set of results + var originalOffset = pageableParameters.Offset; + + // Reset offset to original value after retrieveing for an eventual reuse of the command somewhere else + pageableParameters.Offset = (originalOffset ?? DefaultOffset) + this.position; + RetrieveResults(command); + pageableParameters.Offset = originalOffset; + } + + return this.position % limit < this.resultSet.Count; + } + + // If command is not paged + if (this.resultSet == null) + { + RetrieveResults(this.command); + } + + return this.position < this.resultSet.Count; + } + + private void RetrieveResults(QueryCommand queryCommand) + { + var queryTask = this.client.ExecuteAsync(queryCommand); + this.resultSet = queryTask.Result.Results; + } + + public void Reset() + { + this.resultSet = null; + this.position = -1; + } + + public TCommand Current + { + get + { + if (this.command.QueryParameters is IPageable pageableParameters) + { + var limit = pageableParameters.Limit ?? DefaultLimit; + return this.resultSet[this.position % limit]; + } + + return this.resultSet[this.position]; + } + } + + object IEnumerator.Current => Current; + + public void Dispose() + { + this.resultSet?.Clear(); + + this.client = null; + this.command = null; + this.resultSet = null; + } + } +} diff --git a/commercetools.Sdk/commercetools.Sdk.Client/ClientQueryProvider.cs b/commercetools.Sdk/commercetools.Sdk.Client/ClientQueryProvider.cs index 9d3785e3..a935d683 100644 --- a/commercetools.Sdk/commercetools.Sdk.Client/ClientQueryProvider.cs +++ b/commercetools.Sdk/commercetools.Sdk.Client/ClientQueryProvider.cs @@ -15,11 +15,17 @@ public class ClientQueryProvider : IQueryProvider private readonly IClient client; private IList result = new List(); + private IEnumerator enumerator; - public ClientQueryProvider(IClient client, QueryCommand command) + public ClientQueryProvider(IClient client, QueryCommand command, bool queryAll) { this.client = client; this.Command = command; + + if (queryAll) + { + enumerator = new ClientQueryAllEnumerator(client, command); + } } public QueryCommand Command { get; } @@ -128,6 +134,12 @@ public object Execute(Expression expression) public TResult Execute(Expression expression) { + if (enumerator != null) + { + enumerator.Reset(); + return (TResult)enumerator; + } + if (this.client == null) { throw new FieldAccessException("Client cannot be null"); diff --git a/commercetools.Sdk/commercetools.Sdk.Client/ClientQueryableCollection.cs b/commercetools.Sdk/commercetools.Sdk.Client/ClientQueryableCollection.cs index 5d48b72d..381e53aa 100644 --- a/commercetools.Sdk/commercetools.Sdk.Client/ClientQueryableCollection.cs +++ b/commercetools.Sdk/commercetools.Sdk.Client/ClientQueryableCollection.cs @@ -11,9 +11,9 @@ namespace commercetools.Sdk.Client public class ClientQueryableCollection : IOrderedQueryable { - public ClientQueryableCollection(IClient client, QueryCommand command) + public ClientQueryableCollection(IClient client, QueryCommand command, bool queryAll = false) { - this.Provider = new ClientQueryProvider(client, command); + this.Provider = new ClientQueryProvider(client, command, queryAll); this.Expression = Expression.Constant(this); } diff --git a/commercetools.Sdk/commercetools.Sdk.Client/LinqExtensions.cs b/commercetools.Sdk/commercetools.Sdk.Client/LinqExtensions.cs index f2de9e1b..20ca6bef 100644 --- a/commercetools.Sdk/commercetools.Sdk.Client/LinqExtensions.cs +++ b/commercetools.Sdk/commercetools.Sdk.Client/LinqExtensions.cs @@ -16,6 +16,11 @@ public static ClientQueryableCollection Query(this IClient client) return new ClientQueryableCollection(client, new QueryCommand()); } + public static ClientQueryableCollection QueryAll(this IClient client) + { + return new ClientQueryableCollection(client, new QueryCommand(), true); + } + public static ClientQueryableCollection SearchProducts(this IClient client) { return new ClientQueryableCollection(client, new SearchProductProjectionsCommand());