using Managing.Infrastructure.Databases.MongoDb.Abstractions; using Managing.Infrastructure.Databases.MongoDb.Attributes; using Managing.Infrastructure.Databases.MongoDb.Configurations; using MongoDB.Bson; using MongoDB.Driver; using System.Linq.Expressions; namespace Managing.Infrastructure.Databases.MongoDb { public class MongoRepository : IMongoRepository where TDocument : IDocument { private readonly IMongoCollection _collection; private readonly IMongoDatabase _database; public MongoRepository(IManagingDatabaseSettings settings) { _database = new MongoClient(settings.ConnectionString).GetDatabase(settings.DatabaseName); _collection = _database.GetCollection(GetCollectionName(typeof(TDocument))); } private protected string GetCollectionName(Type documentType) { return ((BsonCollectionAttribute)documentType.GetCustomAttributes( typeof(BsonCollectionAttribute), true) .FirstOrDefault())?.CollectionName; } public virtual IQueryable AsQueryable() { return _collection.AsQueryable(); } public virtual IEnumerable FilterBy( Expression> filterExpression) { return _collection.Find(filterExpression).ToEnumerable(); } public virtual IEnumerable FilterBy(FilterDefinition filter) { return _collection.Find(filter).ToEnumerable(); } public virtual IEnumerable FindAll() { return _collection.Find(_ => true).ToEnumerable(); } public virtual IEnumerable FilterBy( Expression> filterExpression, Expression> projectionExpression) { return _collection.Find(filterExpression).Project(projectionExpression).ToEnumerable(); } public virtual TDocument FindOne(Expression> filterExpression) { return _collection.Find(filterExpression).FirstOrDefault(); } public virtual Task FindOneAsync(Expression> filterExpression) { return Task.Run(() => _collection.Find(filterExpression).FirstOrDefaultAsync()); } public virtual TDocument FindById(string id) { var objectId = new ObjectId(id); var filter = Builders.Filter.Eq(doc => doc.Id, objectId); return _collection.Find(filter).SingleOrDefault(); } public virtual Task FindByIdAsync(string id) { return Task.Run(() => { var objectId = new ObjectId(id); var filter = Builders.Filter.Eq(doc => doc.Id, objectId); return _collection.Find(filter).SingleOrDefaultAsync(); }); } public virtual void InsertOne(TDocument document) { _collection.InsertOne(document); } public virtual Task InsertOneAsync(TDocument document) { return Task.Run(() => _collection.InsertOneAsync(document)); } public void InsertMany(ICollection documents) { _collection.InsertMany(documents); } public void DropCollection() { _database.DropCollection(GetCollectionName(typeof(TDocument))); } public virtual async Task InsertManyAsync(ICollection documents) { await _collection.InsertManyAsync(documents); } public void ReplaceOne(TDocument document) { var filter = Builders.Filter.Eq(doc => doc.Id, document.Id); _collection.FindOneAndReplace(filter, document); } public virtual async Task ReplaceOneAsync(TDocument document) { var filter = Builders.Filter.Eq(doc => doc.Id, document.Id); await _collection.FindOneAndReplaceAsync(filter, document); } public virtual void Update(TDocument entity) { if (entity.Id == ObjectId.Empty) { entity.Id = ObjectId.GenerateNewId(); } var option = new ReplaceOptions { IsUpsert = true }; _collection.ReplaceOne(x => entity != null && x.Id == entity.Id, entity, option); } public virtual void DeleteOne(Expression> filterExpression) { _collection.FindOneAndDelete(filterExpression); } public virtual Task DeleteOneAsync(Expression> filterExpression) { return Task.Run(() => _collection.FindOneAndDeleteAsync(filterExpression)); } public virtual void DeleteById(string id) { var objectId = new ObjectId(id); var filter = Builders.Filter.Eq(doc => doc.Id, objectId); _collection.FindOneAndDelete(filter); } public virtual Task DeleteByIdAsync(string id) { return Task.Run(() => { var objectId = new ObjectId(id); var filter = Builders.Filter.Eq(doc => doc.Id, objectId); _collection.FindOneAndDeleteAsync(filter); }); } public virtual void DeleteMany(Expression> filterExpression) { _collection.DeleteMany(filterExpression); } public virtual Task DeleteManyAsync(Expression> filterExpression) { return _collection.DeleteManyAsync(filterExpression); } public virtual void CreateIndex(string column) { var keys = Builders.IndexKeys.Ascending(column); var indexOptions = new CreateIndexOptions { Unique = true }; var model = new CreateIndexModel(keys, indexOptions); _collection.Indexes.CreateOne(model); } } }