278 lines
11 KiB
C#
278 lines
11 KiB
C#
using System.Linq.Expressions;
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
using MongoDB.Bson.Serialization;
|
|
using MongoDB.Driver;
|
|
|
|
using DomainResults.Common;
|
|
|
|
using Core.Abstractions.DomainObjects;
|
|
|
|
namespace DataProviders.Abstractions {
|
|
public abstract class DataProviderBase<T> where T : DomainObjectDocumentBase<T> {
|
|
|
|
private protected const string _databaseName = "reactredux";
|
|
|
|
private protected readonly ILogger<DataProviderBase<T>> _logger;
|
|
private protected readonly IMongoClient _client;
|
|
private protected readonly IIdGenerator _idGenerator;
|
|
private protected readonly ISessionService _sessionService;
|
|
|
|
private protected List<T>? _collection;
|
|
|
|
/// <summary>
|
|
/// Main constructor
|
|
/// </summary>
|
|
/// <param name="logger"></param>
|
|
/// <param name="client"></param>
|
|
/// <param name="idGenerator"></param>
|
|
/// <param name="dataProviderUtils"></param>
|
|
public DataProviderBase(
|
|
ILogger<DataProviderBase<T>> logger,
|
|
IMongoClient client,
|
|
IIdGenerator idGenerator,
|
|
ISessionService sessionService
|
|
) {
|
|
_logger = logger;
|
|
_client = client;
|
|
_idGenerator = idGenerator;
|
|
_sessionService = sessionService;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Testing constructor
|
|
/// </summary>
|
|
/// <param name="logger"></param>
|
|
/// <param name="collection"></param>
|
|
public DataProviderBase(
|
|
ILogger<DataProviderBase<T>> logger,
|
|
ISessionService sessionService,
|
|
List<T> collection
|
|
) {
|
|
_logger = logger;
|
|
_sessionService = sessionService;
|
|
_collection = collection ?? new List<T>();
|
|
}
|
|
|
|
#region Insert
|
|
private protected (Guid?, IDomainResult) Insert(T obj, string collectionName) =>
|
|
InsertAsync(obj, collectionName).Result;
|
|
|
|
private protected (Guid?, IDomainResult) Insert(T obj, string collectionName, Guid sessionId) =>
|
|
InsertAsync(obj, collectionName, sessionId).Result;
|
|
|
|
private protected Task<(Guid?, IDomainResult)> InsertAsync(T obj, string collectionName) =>
|
|
InsertAsyncCore(obj, collectionName, null);
|
|
|
|
private protected Task<(Guid?, IDomainResult)> InsertAsync(T obj, string collectionName, Guid sessionId) =>
|
|
InsertAsyncCore(obj, collectionName, sessionId);
|
|
#endregion
|
|
|
|
#region InsertMany
|
|
private protected (List<Guid>?, IDomainResult) InsertMany(List<T> objList, string collectionName) =>
|
|
InsertManyAsync(objList, collectionName).Result;
|
|
|
|
private protected (List<Guid>?, IDomainResult) InsertMany(List<T> objList, string collectionName, Guid sessionId) =>
|
|
InsertManyAsync(objList, collectionName, sessionId).Result;
|
|
|
|
private protected Task<(List<Guid>?, IDomainResult)> InsertManyAsync(List<T> objList, string collectionName) =>
|
|
InsertManyAsyncCore(objList, collectionName, null);
|
|
|
|
private protected Task<(List<Guid>?, IDomainResult)> InsertManyAsync(List<T> objList, string collectionName, Guid sessionId) =>
|
|
InsertManyAsyncCore(objList, collectionName, sessionId);
|
|
#endregion
|
|
|
|
#region Get
|
|
private protected (List<T>?, IDomainResult) GetWithPredicate(Expression<Func<T, bool>> predicate, string collectionName) =>
|
|
GetWithPredicateCore(predicate, collectionName);
|
|
#endregion
|
|
|
|
#region Update
|
|
private protected (Guid?, IDomainResult) UpdateWithPredicate(T obj, Expression<Func<T, bool>> predicate, string collectionName) =>
|
|
UpdateWithPredicateAsync(obj, predicate, collectionName).Result;
|
|
|
|
private protected (Guid?, IDomainResult) UpdateWithPredicate(T obj, Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
|
UpdateWithPredicateAsync(obj, predicate, collectionName, sessionId).Result;
|
|
|
|
private protected Task<(Guid?, IDomainResult)> UpdateWithPredicateAsync(T obj, Expression<Func<T, bool>> predicate, string collectionName) =>
|
|
UpdateWithPredicateAsyncCore(obj, predicate, collectionName, null);
|
|
|
|
private protected Task<(Guid?, IDomainResult)> UpdateWithPredicateAsync(T obj, Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
|
UpdateWithPredicateAsyncCore(obj, predicate, collectionName, sessionId);
|
|
#endregion
|
|
|
|
#region Exists
|
|
private protected (Guid?, IDomainResult) Exists(Guid id, string collectionName) {
|
|
var (_resultList, result) = GetWithPredicate(x => x.Id == id, collectionName);
|
|
|
|
return (result.Status != DomainOperationStatus.Failed && _resultList != null && _resultList.Count > 0
|
|
? id
|
|
:null,
|
|
result);
|
|
}
|
|
#endregion
|
|
|
|
#region Delete
|
|
private protected IDomainResult DeleteWithPredicate(Expression<Func<T, bool>> predicate, string collectionName) =>
|
|
DeleteWithPredicateAsync(predicate, collectionName).Result;
|
|
|
|
private protected IDomainResult DeleteWithPredicate(Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
|
DeleteWithPredicateAsync(predicate, collectionName, sessionId).Result;
|
|
|
|
private protected Task<IDomainResult> DeleteWithPredicateAsync(Expression<Func<T, bool>> predicate, string collectionName) =>
|
|
DeleteWithPredicateAsyncCore(predicate, collectionName, null);
|
|
|
|
private protected Task<IDomainResult> DeleteWithPredicateAsync(Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
|
DeleteWithPredicateAsyncCore(predicate, collectionName, sessionId);
|
|
#endregion
|
|
|
|
|
|
#region DeleteMany
|
|
private protected IDomainResult DeleteManyWithPredicate(Expression<Func<T, bool>> predicate, string collectionName) =>
|
|
DeleteManyWithPredicateAsync(predicate, collectionName).Result;
|
|
|
|
private protected IDomainResult DeleteManyWithPredicate(Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
|
DeleteManyWithPredicateAsync(predicate, collectionName, sessionId).Result;
|
|
|
|
private protected Task<IDomainResult> DeleteManyWithPredicateAsync(Expression<Func<T, bool>> predicate, string collectionName) =>
|
|
DeleteManyWithPredicateAsyncCore(predicate, collectionName, null);
|
|
|
|
private protected Task<IDomainResult> DeleteManyWithPredicateAsync(Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
|
DeleteManyWithPredicateAsyncCore(predicate, collectionName, sessionId);
|
|
#endregion
|
|
|
|
|
|
#region Core methods
|
|
private async protected Task<(Guid?, IDomainResult)> InsertAsyncCore(T obj, string collectionName, Guid? sessionId) {
|
|
try {
|
|
if (_collection != null) {
|
|
obj.Id = Guid.NewGuid();
|
|
_collection.Add(obj);
|
|
return IDomainResult.Success(obj.Id);
|
|
}
|
|
|
|
var collection = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName);
|
|
|
|
if (sessionId != null)
|
|
await collection.InsertOneAsync(_sessionService.GetSession(sessionId.Value), obj);
|
|
else
|
|
collection.InsertOne(obj);
|
|
|
|
return IDomainResult.Success(obj.Id);
|
|
}
|
|
catch (Exception ex) {
|
|
_logger.LogError(ex, "Data provider error");
|
|
return IDomainResult.Failed<Guid?>();
|
|
}
|
|
}
|
|
|
|
private async Task<(List<Guid>?, IDomainResult)> InsertManyAsyncCore(List<T> objList, string collectionName, Guid? sessionId) {
|
|
try {
|
|
if (_collection != null) {
|
|
_collection = _collection.Concat(objList).ToList();
|
|
return IDomainResult.Success(objList.Select(x => x.Id).ToList());
|
|
}
|
|
|
|
var collection = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName);
|
|
|
|
if (sessionId != null)
|
|
await collection.InsertManyAsync(_sessionService.GetSession(sessionId.Value), objList);
|
|
else
|
|
collection.InsertMany(objList);
|
|
|
|
return IDomainResult.Success(objList.Select(x => x.Id).ToList());
|
|
}
|
|
catch (Exception ex) {
|
|
_logger.LogError(ex, "Data provider error");
|
|
return IDomainResult.Failed<List<Guid>?>();
|
|
}
|
|
}
|
|
|
|
private (List<T>?, IDomainResult) GetWithPredicateCore(Expression<Func<T, bool>> predicate, string collectionName) {
|
|
try {
|
|
List<T>? result;
|
|
|
|
if (_collection != null) {
|
|
result = _collection?.AsQueryable()
|
|
.Where(predicate).ToList();
|
|
}
|
|
else {
|
|
result = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName)
|
|
.Find(predicate).ToList();
|
|
}
|
|
|
|
return result != null && result.Count > 0
|
|
? IDomainResult.Success(result)
|
|
: IDomainResult.NotFound<List<T>?>();
|
|
}
|
|
catch (Exception ex) {
|
|
_logger.LogError(ex, "Data provider error");
|
|
return IDomainResult.Failed<List<T>?>();
|
|
}
|
|
}
|
|
|
|
private async Task<(Guid?, IDomainResult)> UpdateWithPredicateAsyncCore(T obj, Expression<Func<T, bool>> predicate, string collectionName, Guid? sessionId) {
|
|
try {
|
|
if (_collection != null) {
|
|
// remove element(s) from list
|
|
foreach (var element in _collection.AsQueryable().Where(predicate))
|
|
_collection = _collection.Where(x => x.Id != element.Id).ToList();
|
|
|
|
// add updated element
|
|
_collection.Add(obj);
|
|
}
|
|
else {
|
|
var collection = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName);
|
|
|
|
if (sessionId != null)
|
|
await collection.ReplaceOneAsync(_sessionService.GetSession(sessionId.Value), predicate, obj);
|
|
else
|
|
await collection.ReplaceOneAsync(predicate, obj);
|
|
}
|
|
|
|
return IDomainResult.Success(obj.Id);
|
|
}
|
|
catch (Exception ex) {
|
|
_logger.LogError(ex, "Data provider error");
|
|
return IDomainResult.Failed<Guid?>();
|
|
}
|
|
}
|
|
|
|
private async Task<IDomainResult> DeleteWithPredicateAsyncCore(Expression<Func<T, bool>> predicate, string collectionName, Guid? sessionId) {
|
|
try {
|
|
var collection = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName);
|
|
|
|
if (sessionId != null)
|
|
await collection.DeleteOneAsync<T>(_sessionService.GetSession(sessionId.Value), predicate);
|
|
else
|
|
await collection.DeleteOneAsync<T>(predicate);
|
|
|
|
return IDomainResult.Success();
|
|
}
|
|
catch (Exception ex) {
|
|
_logger.LogError(ex, "Data provider error");
|
|
return IDomainResult.Failed();
|
|
}
|
|
}
|
|
|
|
private async Task<IDomainResult> DeleteManyWithPredicateAsyncCore(Expression<Func<T, bool>> predicate, string collectionName, Guid? sessionId) {
|
|
try {
|
|
var collection = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName);
|
|
|
|
if (sessionId != null)
|
|
await collection.DeleteManyAsync(_sessionService.GetSession(sessionId.Value), predicate);
|
|
else
|
|
await collection.DeleteManyAsync(predicate);
|
|
|
|
return IDomainResult.Success();
|
|
}
|
|
catch (Exception ex) {
|
|
_logger.LogError(ex, "Data provider error");
|
|
return IDomainResult.Failed();
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
}
|