2020-08-09 01:31:16 +02:00
|
|
|
|
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<IEnumerable<TSelect>> GetItems<T, TSelect>(
|
|
|
|
|
Expression<Func<T, TSelect>> selectExpression,
|
2020-08-09 02:26:41 +02:00
|
|
|
|
Expression<Func<T, bool>> whereExpression = null,
|
|
|
|
|
string partitionKey = null)
|
2020-08-09 01:31:16 +02:00
|
|
|
|
where T : IIdentifiable
|
|
|
|
|
{
|
2020-08-09 02:52:26 +02:00
|
|
|
|
ArgumentUtility.CheckForNull(selectExpression, nameof(selectExpression));
|
|
|
|
|
|
2020-08-09 02:26:41 +02:00
|
|
|
|
if (partitionKey == null)
|
|
|
|
|
{
|
|
|
|
|
partitionKey = typeof(T).Name;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-09 01:31:16 +02:00
|
|
|
|
IQueryable<T> query = this.container
|
|
|
|
|
.GetItemLinqQueryable<T>(requestOptions: new QueryRequestOptions
|
|
|
|
|
{
|
|
|
|
|
PartitionKey = new PartitionKey(partitionKey),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (whereExpression != null)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(whereExpression);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var feedIteratorQuery = query
|
|
|
|
|
.Select(selectExpression)
|
|
|
|
|
.ToFeedIterator();
|
|
|
|
|
|
|
|
|
|
var items = new List<TSelect>();
|
|
|
|
|
while (feedIteratorQuery.HasMoreResults)
|
|
|
|
|
{
|
|
|
|
|
var results = await feedIteratorQuery.ReadNextAsync();
|
|
|
|
|
foreach (var result in results)
|
|
|
|
|
{
|
|
|
|
|
items.Add(result);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return items;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<IEnumerable<T>> GetItems<T>(
|
|
|
|
|
Expression<Func<T, bool>> whereExpression = null,
|
|
|
|
|
string partitionKey = null)
|
|
|
|
|
where T : IIdentifiable
|
|
|
|
|
{
|
|
|
|
|
if (partitionKey == null)
|
|
|
|
|
{
|
|
|
|
|
partitionKey = typeof(T).Name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IQueryable<T> query = this.container
|
|
|
|
|
.GetItemLinqQueryable<T>(requestOptions: new QueryRequestOptions
|
|
|
|
|
{
|
|
|
|
|
PartitionKey = new PartitionKey(partitionKey),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (whereExpression != null)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(whereExpression);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var feedIteratorQuery = query
|
|
|
|
|
.ToFeedIterator();
|
|
|
|
|
|
|
|
|
|
var items = new List<T>();
|
|
|
|
|
while (feedIteratorQuery.HasMoreResults)
|
|
|
|
|
{
|
|
|
|
|
var results = await feedIteratorQuery.ReadNextAsync();
|
|
|
|
|
foreach (var result in results)
|
|
|
|
|
{
|
|
|
|
|
items.Add(result);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return items;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<T> GetItemById<T>(string id, string partitionKey = null)
|
|
|
|
|
where T : IIdentifiable
|
|
|
|
|
{
|
2020-08-09 02:52:26 +02:00
|
|
|
|
ArgumentUtility.CheckStringForNullOrEmpty(id, nameof(id));
|
|
|
|
|
|
2020-08-09 01:31:16 +02:00
|
|
|
|
return (await this.GetItems<T>(t => t.id == id, partitionKey)).FirstOrDefault();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task UpsertItem<T>(
|
|
|
|
|
T item,
|
|
|
|
|
PartitionKey? partitionKey = null,
|
|
|
|
|
ItemRequestOptions itemRequestOptions = null)
|
|
|
|
|
where T : IIdentifiable
|
|
|
|
|
{
|
2020-08-09 02:52:26 +02:00
|
|
|
|
ArgumentUtility.CheckForNull(item, nameof(item));
|
|
|
|
|
|
2020-08-09 01:31:16 +02:00
|
|
|
|
await this.container.UpsertItemAsync(item, partitionKey, itemRequestOptions);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task Initialize(string partitionKeyPath = null)
|
|
|
|
|
{
|
2020-08-10 09:22:33 +02:00
|
|
|
|
// TODO: Use static shared cosmos client
|
2020-08-09 01:31:16 +02:00
|
|
|
|
this.client = new CosmosClient(
|
|
|
|
|
this.connectionString,
|
|
|
|
|
this.authKeyOrResourceToken);
|
|
|
|
|
|
2020-08-10 09:22:33 +02:00
|
|
|
|
var databaseResponse = await this.client.CreateDatabaseIfNotExistsAsync(this.databaseId);
|
2020-08-09 01:31:16 +02:00
|
|
|
|
var containerResponse = await databaseResponse.Database.CreateContainerIfNotExistsAsync(new ContainerProperties()
|
|
|
|
|
{
|
|
|
|
|
Id = containerId,
|
|
|
|
|
PartitionKeyPath = partitionKeyPath ?? "/DocumentType"
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.container = containerResponse.Container;
|
|
|
|
|
}
|
2020-08-09 02:26:41 +02:00
|
|
|
|
|
|
|
|
|
public async Task DeleteItem<T>(
|
|
|
|
|
string id,
|
|
|
|
|
string partitionKey = null,
|
|
|
|
|
ItemRequestOptions requestOptions = null)
|
|
|
|
|
{
|
2020-08-09 02:52:26 +02:00
|
|
|
|
ArgumentUtility.CheckStringForNullOrEmpty(id, nameof(id));
|
|
|
|
|
|
2020-08-09 02:26:41 +02:00
|
|
|
|
if (partitionKey == null)
|
|
|
|
|
{
|
|
|
|
|
partitionKey = typeof(T).Name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
await this.container.DeleteItemAsync<T>(id, new PartitionKey(partitionKey), requestOptions);
|
|
|
|
|
}
|
|
|
|
|
catch (CosmosException e) when (e.StatusCode == System.Net.HttpStatusCode.NotFound)
|
|
|
|
|
{
|
|
|
|
|
// Ignore
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-08-09 01:31:16 +02:00
|
|
|
|
}
|
|
|
|
|
}
|