using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Threading; using System.Threading.Tasks; using MongoDB.Bson.Serialization.Attributes; using MongoDB.Driver; using PoweredSoft.DynamicLinq.Helpers; using PoweredSoft.ObjectStorage.Core; namespace PoweredSoft.ObjectStorage.MongoDB { public class MongoObjectStorageCollection : IObjectStorageCollection { public MongoObjectStorageCollection(IMongoCollection collection) { if (collection == null) throw new ArgumentNullException("collection"); Collection = collection; } public string CollectionName => Collection.CollectionNamespace.CollectionName; public IMongoCollection Collection { get; } public async Task AddAsync(TEntity entity, CancellationToken cancellationToken = default(CancellationToken)) { await Collection.InsertOneAsync(entity, cancellationToken: cancellationToken); return entity; } public IQueryable AsQueryable() { return Collection.AsQueryable(); } protected virtual Expression> CreateEntityExpression(TEntity entity) { var objectKey = GetBsonIdProperty(); var constant = objectKey.GetValue(entity); var expression = QueryableHelpers.CreateConditionExpression(objectKey.Name, DynamicLinq.ConditionOperators.Equal, constant, DynamicLinq.QueryConvertStrategy.LeaveAsIs); return expression; } protected virtual PropertyInfo GetBsonIdProperty() { var objectKey = typeof(TEntity) .GetProperties(BindingFlags.Public | BindingFlags.Instance) .FirstOrDefault(t => t.GetCustomAttribute() != null); if (objectKey == null) throw new Exception("Must have a BsonIdAttribute on one of the properties."); return objectKey; } public async Task DeleteAsync(TEntity entity, CancellationToken cancellationToken = default(CancellationToken)) { var expression = CreateEntityExpression(entity); await Collection.DeleteOneAsync(expression); } public async Task UpdateAsync(TEntity entity, CancellationToken cancellationToken = default(CancellationToken)) { var expression = CreateEntityExpression(entity); await Collection.ReplaceOneAsync(expression, entity); return entity; } public Task> GetAllAsync(CancellationToken cancellationToken = default(CancellationToken)) { return Collection.AsQueryable().ToListAsync(cancellationToken); } public Task> GetAllAsync(Expression> predicate, CancellationToken cancellationToken = default(CancellationToken)) { return Collection.Find(predicate).ToListAsync(cancellationToken); } public Task GetAsync(object key, CancellationToken cancellationToken = default(CancellationToken)) { var keyProp = GetBsonIdProperty(); var expression = QueryableHelpers.CreateConditionExpression(keyProp.Name, DynamicLinq.ConditionOperators.Equal, key, DynamicLinq.QueryConvertStrategy.LeaveAsIs); var result = Collection.Find(expression).FirstOrDefaultAsync(); return result; } public List GetObjectKeys() { return new List() { GetBsonIdProperty() }; } } }