253 lines
12 KiB
C#
253 lines
12 KiB
C#
using MongoDB.Bson;
|
|
using MongoDB.Driver;
|
|
using MongoDB.Driver.Linq;
|
|
using System.Linq.Expressions;
|
|
using System.Reflection;
|
|
|
|
namespace Core.Blueprint.Mongo
|
|
{
|
|
/// <summary>
|
|
/// Provides methods for interacting with a MongoDB collection for a specific document type.
|
|
/// Inherits from <see cref="MongoProvider"/> and implements <see cref="ICollectionsRepository{TDocument}"/>.
|
|
/// This class encapsulates common database operations such as querying, inserting, updating, and deleting documents.
|
|
/// </summary>
|
|
/// <typeparam name="TDocument">The type of document stored in the collection, which must implement <see cref="IDocument"/>.</typeparam>
|
|
public class CollectionRepository<TDocument>(IMongoDatabase database) : ICollectionsRepository<TDocument> where TDocument : IDocument
|
|
{
|
|
private IMongoCollection<TDocument> _collection;
|
|
|
|
/// <summary>
|
|
/// Initializes the MongoDB collection based on the <see cref="CollectionAttributeName"/> attribute
|
|
/// applied to the <typeparamref name="TDocument"/> type. Throws an exception if the attribute is not present.
|
|
/// </summary>
|
|
public void CollectionInitialization()
|
|
{
|
|
var collectionAttribute = typeof(TDocument).GetCustomAttribute<CollectionAttributeName>();
|
|
if (collectionAttribute == null)
|
|
{
|
|
throw new InvalidOperationException($"The class {typeof(TDocument).Name} is missing the CollectionAttributeName attribute.");
|
|
}
|
|
|
|
string collectionName = collectionAttribute.Name;
|
|
|
|
_collection = database.GetCollection<TDocument>(collectionName);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns all documents from the collection as an enumerable list.
|
|
/// </summary>
|
|
/// <returns>A task that represents the asynchronous operation. The task result contains an enumerable list of documents.</returns>
|
|
public virtual async ValueTask<IEnumerable<TDocument>> AsQueryable()
|
|
{
|
|
return await _collection.AsQueryable().ToListAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Filters documents in the collection based on the provided filter expression.
|
|
/// </summary>
|
|
/// <param name="filterExpression">A lambda expression that defines the filter criteria for the documents.</param>
|
|
/// <returns>A task that represents the asynchronous operation. The task result contains a list of documents that match the filter.</returns>
|
|
public virtual async Task<IEnumerable<TDocument>> FilterBy(
|
|
Expression<Func<TDocument, bool>> filterExpression)
|
|
{
|
|
var objectResult = await _collection.FindAsync(filterExpression).ConfigureAwait(false);
|
|
return objectResult.ToList();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Filters documents in the collection based on the provided filter and projection expressions.
|
|
/// Projects the filtered documents into a new type.
|
|
/// </summary>
|
|
/// <typeparam name="TProjected">The type to project the documents into.</typeparam>
|
|
/// <param name="filterExpression">A lambda expression that defines the filter criteria for the documents.</param>
|
|
/// <param name="projectionExpression">A lambda expression that defines how the documents should be projected.</param>
|
|
/// <returns>An enumerable collection of projected documents.</returns>
|
|
public virtual IEnumerable<TProjected> FilterBy<TProjected>(
|
|
Expression<Func<TDocument, bool>> filterExpression,
|
|
Expression<Func<TDocument, TProjected>> projectionExpression)
|
|
{
|
|
return _collection.Find(filterExpression).Project(projectionExpression).ToEnumerable();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Finds a single document that matches the provided filter expression.
|
|
/// </summary>
|
|
/// <param name="filterExpression">A lambda expression that defines the filter criteria for the document.</param>
|
|
/// <returns>The document that matches the filter, or <c>null</c> if no document is found.</returns>
|
|
public virtual TDocument FindOne(Expression<Func<TDocument, bool>> filterExpression)
|
|
{
|
|
return _collection.Find(filterExpression).FirstOrDefault();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Filters documents in the collection based on the provided MongoDB filter definition.
|
|
/// </summary>
|
|
/// <param name="filterDefinition">A filter definition for MongoDB query.</param>
|
|
/// <returns>A task that represents the asynchronous operation. The task result contains a list of documents that match the filter.</returns>
|
|
public virtual async Task<IEnumerable<TDocument>> FilterByMongoFilterAsync(FilterDefinition<TDocument> filterDefinition)
|
|
{
|
|
var objectResult = await _collection.Find(filterDefinition).ToListAsync().ConfigureAwait(false);
|
|
return objectResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Asynchronously finds a single document that matches the provided filter expression.
|
|
/// </summary>
|
|
/// <param name="filterExpression">A lambda expression that defines the filter criteria for the document.</param>
|
|
/// <returns>A task that represents the asynchronous operation. The task result contains the document that matches the filter, or <c>null</c> if no document is found.</returns>
|
|
public virtual Task<TDocument> FindOneAsync(Expression<Func<TDocument, bool>> filterExpression)
|
|
{
|
|
return Task.Run(() => _collection.Find(filterExpression).FirstOrDefaultAsync());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Finds a document by its unique identifier (ID).
|
|
/// </summary>
|
|
/// <param name="id">The unique identifier of the document.</param>
|
|
/// <returns>The document that matches the specified ID, or <c>null</c> if no document is found.</returns>
|
|
public virtual TDocument FindById(string id)
|
|
{
|
|
var filter = Builders<TDocument>.Filter.Eq(doc => doc._Id, id);
|
|
return _collection.Find(filter).SingleOrDefault();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Asynchronously finds a document by its unique identifier (ID).
|
|
/// </summary>
|
|
/// <param name="id">The unique identifier of the document.</param>
|
|
/// <returns>A task that represents the asynchronous operation. The task result contains the document that matches the specified ID, or <c>null</c> if no document is found.</returns>
|
|
public virtual Task<TDocument> FindByIdAsync(string id)
|
|
{
|
|
return Task.Run(() =>
|
|
{
|
|
var objectId = new ObjectId(id);
|
|
var filter = Builders<TDocument>.Filter.Eq(doc => doc._Id, id);
|
|
return _collection.Find(filter).SingleOrDefaultAsync();
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inserts a single document into the collection.
|
|
/// </summary>
|
|
/// <param name="document">The document to insert.</param>
|
|
public virtual void InsertOne(TDocument document)
|
|
{
|
|
_collection.InsertOne(document);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Asynchronously inserts a single document into the collection.
|
|
/// </summary>
|
|
/// <param name="document">The document to insert.</param>
|
|
/// <returns>A task that represents the asynchronous operation.</returns>
|
|
public virtual Task InsertOneAsync(TDocument document)
|
|
{
|
|
return Task.Run(() => _collection.InsertOneAsync(document));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inserts multiple documents into the collection.
|
|
/// </summary>
|
|
/// <param name="documents">The collection of documents to insert.</param>
|
|
public void InsertMany(ICollection<TDocument> documents)
|
|
{
|
|
_collection.InsertMany(documents);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Asynchronously inserts multiple documents into the collection.
|
|
/// </summary>
|
|
/// <param name="documents">The collection of documents to insert.</param>
|
|
/// <returns>A task that represents the asynchronous operation.</returns>
|
|
public virtual async Task InsertManyAsync(ICollection<TDocument> documents)
|
|
{
|
|
await _collection.InsertManyAsync(documents);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Replaces an existing document in the collection.
|
|
/// </summary>
|
|
/// <param name="document">The document with the updated data.</param>
|
|
public void ReplaceOne(TDocument document)
|
|
{
|
|
var filter = Builders<TDocument>.Filter.Eq(doc => doc._Id, document._Id);
|
|
_collection.FindOneAndReplace(filter, document);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Asynchronously replaces an existing document in the collection.
|
|
/// </summary>
|
|
/// <param name="document">The document with the updated data.</param>
|
|
/// <returns>A task that represents the asynchronous operation.</returns>
|
|
public virtual async Task ReplaceOneAsync(TDocument document)
|
|
{
|
|
var filter = Builders<TDocument>.Filter.Eq(doc => doc._Id, document._Id);
|
|
await _collection.FindOneAndReplaceAsync(filter, document);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deletes a single document from the collection based on the provided filter expression.
|
|
/// </summary>
|
|
/// <param name="filterExpression">A lambda expression that defines the filter criteria for the document to delete.</param>
|
|
public void DeleteOne(Expression<Func<TDocument, bool>> filterExpression)
|
|
{
|
|
_collection.FindOneAndDelete(filterExpression);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Asynchronously deletes a single document from the collection based on the provided filter expression.
|
|
/// </summary>
|
|
/// <param name="filterExpression">A lambda expression that defines the filter criteria for the document to delete.</param>
|
|
/// <returns>A task that represents the asynchronous operation.</returns>
|
|
public async Task<TDocument> DeleteOneAsync(Expression<Func<TDocument, bool>> filterExpression)
|
|
{
|
|
return await _collection.FindOneAndDeleteAsync(filterExpression);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deletes a single document from the collection based on its unique identifier (ID).
|
|
/// </summary>
|
|
/// <param name="id">The unique identifier of the document to delete.</param>
|
|
public void DeleteById(string id)
|
|
{
|
|
var objectId = new ObjectId(id);
|
|
var filter = Builders<TDocument>.Filter.Eq(doc => doc._Id, id);
|
|
_collection.FindOneAndDelete(filter);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Asynchronously deletes a single document from the collection based on its unique identifier (ID).
|
|
/// </summary>
|
|
/// <param name="id">The unique identifier of the document to delete.</param>
|
|
/// <returns>A task that represents the asynchronous operation.</returns>
|
|
public Task DeleteByIdAsync(string id)
|
|
{
|
|
return Task.Run(() =>
|
|
{
|
|
var objectId = new ObjectId(id);
|
|
var filter = Builders<TDocument>.Filter.Eq(doc => doc._Id, id);
|
|
_collection.FindOneAndDeleteAsync(filter);
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deletes multiple documents from the collection based on the provided filter expression.
|
|
/// </summary>
|
|
/// <param name="filterExpression">A lambda expression that defines the filter criteria for the documents to delete.</param>
|
|
public void DeleteMany(Expression<Func<TDocument, bool>> filterExpression)
|
|
{
|
|
_collection.DeleteMany(filterExpression);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Asynchronously deletes multiple documents from the collection based on the provided filter expression.
|
|
/// </summary>
|
|
/// <param name="filterExpression">A lambda expression that defines the filter criteria for the documents to delete.</param>
|
|
/// <returns>A task that represents the asynchronous operation.</returns>
|
|
public Task DeleteManyAsync(Expression<Func<TDocument, bool>> filterExpression)
|
|
{
|
|
return Task.Run(() => _collection.DeleteManyAsync(filterExpression));
|
|
}
|
|
}
|
|
}
|