azure-iot-remote-monitoring/Common/Helpers/DocumentDBClient.cs

142 строки
5.1 KiB
C#

using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Microsoft.Azure.Devices.Applications.RemoteMonitoring.Common.Configurations;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Newtonsoft.Json;
namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Common.Helpers
{
/// <summary>
/// Wrapper over document db client.
/// </summary>
/// <typeparam name="T"></typeparam>
public class DocumentDBClient<T> : IDocumentDBClient<T> where T : new()
{
private bool _initialized;
private readonly string _databaseId;
private readonly string _collectionName;
private readonly DocumentClient _client;
private readonly object _initializeLock = new Object();
/// <summary>
/// Creates a new instance of <see cref="DocumentDBClient"/>
/// </summary>
/// <param name="configurationProvider"></param>
public DocumentDBClient(IConfigurationProvider configurationProvider)
{
string endpointUrl = configurationProvider.GetConfigurationSettingValue("docdb.EndpointUrl");
string primaryAuthorizationKey = configurationProvider.GetConfigurationSettingValue("docdb.PrimaryAuthorizationKey");
_client = new DocumentClient(new Uri(endpointUrl), primaryAuthorizationKey);
_databaseId = configurationProvider.GetConfigurationSettingValue("docdb.DatabaseId");
_collectionName = configurationProvider.GetConfigurationSettingValue("docdb.DocumentCollectionId");
}
/// <summary>
/// Gets a document by its id.
/// </summary>
/// <param name="id">The id of the document to get</param>
public async Task<T> GetAsync(string id)
{
await InitializeDatabaseIfRequired();
var response = await _client.ReadDocumentAsync(UriFactory.CreateDocumentUri(_databaseId, _collectionName, id));
return await Deserialize(response.Resource);
}
/// <summary>
/// Returns a <see cref="IQueryable{T}"/> that can be used to query db.
/// </summary>
public async Task<IQueryable<T>> QueryAsync()
{
await InitializeDatabaseIfRequired();
return _client.CreateDocumentQuery<T>(UriFactory.CreateDocumentCollectionUri(_databaseId, _collectionName));
}
/// <summary>
/// Saves a document to the the db.
/// </summary>
/// <param name="data">The data of the document to save.</param>
public async Task<T> SaveAsync(T data)
{
await InitializeDatabaseIfRequired();
var response = await _client.UpsertDocumentAsync(UriFactory.CreateDocumentCollectionUri(_databaseId, _collectionName), data);
return await Deserialize(response.Resource);
}
/// <summary>
/// Deletes a document from the db.
/// </summary>
/// <param name="id">The id of the document to delete</param>
public async Task DeleteAsync(string id)
{
await InitializeDatabaseIfRequired();
await _client.DeleteDocumentAsync(UriFactory.CreateDocumentUri(_databaseId, _collectionName, id));
}
private async Task InitializeDatabaseIfRequired()
{
if (!_initialized)
{
await InitializeDatabase();
await InitializeCollection();
_initialized = true;
}
}
private async Task InitializeDatabase()
{
try
{
await _client.ReadDatabaseAsync(UriFactory.CreateDatabaseUri(_databaseId));
}
catch (DocumentClientException dce)
{
if (dce.StatusCode == HttpStatusCode.NotFound)
{
await _client.CreateDatabaseAsync(new Database { Id = _databaseId });
return;
}
throw;
}
}
private async Task InitializeCollection()
{
try
{
await _client.ReadDocumentCollectionAsync(UriFactory.CreateDocumentCollectionUri(_databaseId, _collectionName));
}
catch (DocumentClientException dce)
{
if (dce.StatusCode == HttpStatusCode.NotFound)
{
await _client.CreateDocumentCollectionAsync(
UriFactory.CreateDatabaseUri(_databaseId),
new DocumentCollection { Id = _collectionName });
return;
}
throw;
}
}
private async Task<T> Deserialize(Document document)
{
using (var documentStream = new MemoryStream())
using (var reader = new StreamReader(documentStream))
{
document.SaveTo(documentStream);
documentStream.Position = 0;
var rawDocumentData = await reader.ReadToEndAsync();
return JsonConvert.DeserializeObject<T>(rawDocumentData);
}
}
}
}