GiantsTools/Giants.Services/Store/CosmosDbClient.cs

169 lines
5.3 KiB
C#

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,
Expression<Func<T, bool>> whereExpression = null,
string partitionKey = null)
where T : IIdentifiable
{
ArgumentUtility.CheckForNull(selectExpression, nameof(selectExpression));
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
.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
{
ArgumentUtility.CheckStringForNullOrEmpty(id, nameof(id));
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
{
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<T>(
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<T>(id, new PartitionKey(partitionKey), requestOptions);
}
catch (CosmosException e) when (e.StatusCode == System.Net.HttpStatusCode.NotFound)
{
// Ignore
}
}
}
}