using System.Linq.Expressions; using Microsoft.Extensions.Logging; using MongoDB.Bson.Serialization; using MongoDB.Driver; using DomainResults.Common; using DomainObjects.Abstractions; namespace DataProviders.Abstractions { /// /// /// /// public abstract class CollectionDataProviderBase : DataProviderBase> where T : DomainObjectDocumentBase { private protected readonly IIdGenerator _idGenerator; private protected readonly ISessionService _sessionService; private protected readonly IMongoCollection _collection; /// /// Main constructor /// /// /// /// /// public CollectionDataProviderBase( ILogger> logger, IMongoClient client, IIdGenerator idGenerator, ISessionService sessionService, string databaseName, string collectionName ) : base (logger, client, databaseName) { _idGenerator = idGenerator; _sessionService = sessionService; _collection = _database.GetCollection(collectionName); } #region Insert public (Guid?, IDomainResult) Insert(T obj) => InsertAsync(obj).Result; public (Guid?, IDomainResult) Insert(T obj, Guid sessionId) => InsertAsync(obj, sessionId).Result; public Task<(Guid?, IDomainResult)> InsertAsync(T obj) => InsertAsync(obj, null); public Task<(Guid?, IDomainResult)> InsertAsync(T obj, Guid sessionId) => InsertAsync(obj, sessionId); private async Task<(Guid?, IDomainResult)> InsertAsync(T obj, Guid? sessionId) { try { 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(); } } #endregion #region InsertMany private protected (List?, IDomainResult) InsertMany(List objList) => InsertManyAsync(objList).Result; private protected (List?, IDomainResult) InsertMany(List objList, Guid sessionId) => InsertManyAsync(objList, sessionId).Result; private protected Task<(List?, IDomainResult)> InsertManyAsync(List objList) => InsertManyAsync(objList, null); private protected Task<(List?, IDomainResult)> InsertManyAsync(List objList, Guid sessionId) => InsertManyAsync(objList, sessionId); private async Task<(List?, IDomainResult)> InsertManyAsync(List objList, Guid? sessionId) { try { 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?>(); } } #endregion #region Get private protected (List?, IDomainResult) GetWithPredicate(Expression> predicate) => GetWithPredicate(predicate, 0, 0); private protected (List?, IDomainResult) GetWithPredicate(Expression> predicate, int skip, int limit) { try { var result = _collection .Find(predicate).Skip(skip).Limit(limit).ToList(); return result != null && result.Count > 0 ? IDomainResult.Success(result) : IDomainResult.NotFound?>(); } catch (Exception ex) { _logger.LogError(ex, "Data provider error"); return IDomainResult.Failed?>(); } } #endregion #region Update private protected (Guid?, IDomainResult) UpdateWithPredicate(T obj, Expression> predicate) => UpdateWithPredicateAsync(obj, predicate).Result; private protected (Guid?, IDomainResult) UpdateWithPredicate(T obj, Expression> predicate, Guid sessionId) => UpdateWithPredicateAsync(obj, predicate, sessionId).Result; private protected Task<(Guid?, IDomainResult)> UpdateWithPredicateAsync(T obj, Expression> predicate) => UpdateWithPredicateAsync(obj, predicate, null); private protected Task<(Guid?, IDomainResult)> UpdateWithPredicateAsync(T obj, Expression> predicate, Guid sessionId) => UpdateWithPredicateAsync(obj, predicate, sessionId); private async Task<(Guid?, IDomainResult)> UpdateWithPredicateAsync(T obj, Expression> predicate, Guid? sessionId) { try { 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(); } } #endregion #region Delete private protected IDomainResult DeleteWithPredicate(Expression> predicate) => DeleteWithPredicateAsync(predicate).Result; private protected IDomainResult DeleteWithPredicate(Expression> predicate, Guid sessionId) => DeleteWithPredicateAsync(predicate, sessionId).Result; private protected Task DeleteWithPredicateAsync(Expression> predicate) => DeleteWithPredicateAsync(predicate, null); private protected Task DeleteWithPredicateAsync(Expression> predicate, Guid sessionId) => DeleteWithPredicateAsync(predicate, sessionId); private async Task DeleteWithPredicateAsync(Expression> predicate, Guid? sessionId) { try { if (sessionId != null) await _collection.DeleteOneAsync(_sessionService.GetSession(sessionId.Value), predicate); else await _collection.DeleteOneAsync(predicate); return IDomainResult.Success(); } catch (Exception ex) { _logger.LogError(ex, "Data provider error"); return IDomainResult.Failed(); } } #endregion #region DeleteMany private protected IDomainResult DeleteManyWithPredicate(Expression> predicate) => DeleteManyWithPredicateAsync(predicate).Result; private protected IDomainResult DeleteManyWithPredicate(Expression> predicate, Guid sessionId) => DeleteManyWithPredicateAsync(predicate, sessionId).Result; private protected Task DeleteManyWithPredicateAsync(Expression> predicate) => DeleteManyWithPredicateAsync(predicate, null); private protected Task DeleteManyWithPredicateAsync(Expression> predicate, Guid sessionId) => DeleteManyWithPredicateAsync(predicate, sessionId); private async Task DeleteManyWithPredicateAsync(Expression> predicate, Guid? sessionId) { try { 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 } }