namespace Giants.Services { using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; using Microsoft.Azure.Cosmos; using Microsoft.Azure.Cosmos.Linq; public class CosmosDbClient { private readonly string connectionString; private readonly string authKeyOrResourceToken; private readonly string databaseId; private readonly string containerId; private CosmosClient client; private Container container; public CosmosDbClient( string connectionString, string authKeyOrResourceToken, string databaseId, string containerId) { this.connectionString = connectionString; this.authKeyOrResourceToken = authKeyOrResourceToken; this.databaseId = databaseId; this.containerId = containerId; } public async Task> GetItems( Expression> selectExpression, Expression> whereExpression = null, string partitionKey = null) where T : IIdentifiable { ArgumentUtility.CheckForNull(selectExpression, nameof(selectExpression)); if (partitionKey == null) { partitionKey = typeof(T).Name; } IQueryable query = this.container .GetItemLinqQueryable(requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey(partitionKey), }); if (whereExpression != null) { query = query.Where(whereExpression); } var feedIteratorQuery = query .Select(selectExpression) .ToFeedIterator(); var items = new List(); while (feedIteratorQuery.HasMoreResults) { var results = await feedIteratorQuery.ReadNextAsync(); foreach (var result in results) { items.Add(result); } } return items; } public async Task> GetItems( Expression> whereExpression = null, string partitionKey = null) where T : IIdentifiable { if (partitionKey == null) { partitionKey = typeof(T).Name; } IQueryable query = this.container .GetItemLinqQueryable(requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey(partitionKey), }); if (whereExpression != null) { query = query.Where(whereExpression); } var feedIteratorQuery = query .ToFeedIterator(); var items = new List(); while (feedIteratorQuery.HasMoreResults) { var results = await feedIteratorQuery.ReadNextAsync(); foreach (var result in results) { items.Add(result); } } return items; } public async Task GetItemById(string id, string partitionKey = null) where T : IIdentifiable { ArgumentUtility.CheckStringForNullOrEmpty(id, nameof(id)); return (await this.GetItems(t => t.id == id, partitionKey)).FirstOrDefault(); } public async Task UpsertItem( T item, PartitionKey? partitionKey = null, ItemRequestOptions itemRequestOptions = null) where T : IIdentifiable { ArgumentUtility.CheckForNull(item, nameof(item)); await this.container.UpsertItemAsync(item, partitionKey, itemRequestOptions); } public async Task Initialize(string partitionKeyPath = null) { // TODO: Use static shared cosmos client this.client = new CosmosClient( this.connectionString, this.authKeyOrResourceToken); var databaseResponse = await this.client.CreateDatabaseIfNotExistsAsync(this.databaseId); var containerResponse = await databaseResponse.Database.CreateContainerIfNotExistsAsync(new ContainerProperties() { Id = containerId, PartitionKeyPath = partitionKeyPath ?? "/DocumentType" }); this.container = containerResponse.Container; } public async Task DeleteItem( string id, string partitionKey = null, ItemRequestOptions requestOptions = null) { ArgumentUtility.CheckStringForNullOrEmpty(id, nameof(id)); if (partitionKey == null) { partitionKey = typeof(T).Name; } try { await this.container.DeleteItemAsync(id, new PartitionKey(partitionKey), requestOptions); } catch (CosmosException e) when (e.StatusCode == System.Net.HttpStatusCode.NotFound) { // Ignore } } } }