using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq.Expressions;
using MongoDbGenericRepository.Models;
using System.Linq;
namespace MongoDbGenericRepository
{
///
/// The ReadOnlyMongoRepository implements the readonly functionality of the IReadOnlyMongoRepository.
///
public class ReadOnlyMongoRepository : IReadOnlyMongoRepository
{
///
/// The connection string.
///
public string ConnectionString { get; set; }
///
/// The database name.
///
public string DatabaseName { get; set; }
///
/// The MongoDbContext
///
protected IMongoDbContext MongoDbContext = null;
///
/// The constructor taking a connection string and a database name.
///
/// The connection string of the MongoDb server.
/// The name of the database against which you want to perform operations.
protected ReadOnlyMongoRepository(string connectionString, string databaseName)
{
MongoDbContext = new MongoDbContext(connectionString, databaseName);
}
///
/// The contructor taking a .
///
/// A mongodb context implementing
protected ReadOnlyMongoRepository(IMongoDbContext mongoDbContext)
{
MongoDbContext = mongoDbContext;
}
///
/// The contructor taking a .
///
/// A mongodb context implementing
protected ReadOnlyMongoRepository(IMongoDatabase mongoDatabase)
{
MongoDbContext = new MongoDbContext(mongoDatabase);
}
#region Read
///
/// Asynchronously returns one document given its id.
///
/// The type representing a Document.
/// The Id of the document you want to get.
/// An optional partition key.
public async Task GetByIdAsync(Guid id, string partitionKey = null) where TDocument : IDocument
{
var filter = Builders.Filter.Eq("Id", id);
return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync();
}
///
/// Returns one document given its id.
///
/// The type representing a Document.
/// The Id of the document you want to get.
/// An optional partition key.
public TDocument GetById(Guid id, string partitionKey = null) where TDocument : IDocument
{
var filter = Builders.Filter.Eq("Id", id);
return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault();
}
///
/// Asynchronously returns one document given an expression filter.
///
/// The type representing a Document.
/// A LINQ expression filter.
/// An optional partition key.
public async Task GetOneAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument
{
return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync();
}
///
/// Returns one document given an expression filter.
///
/// The type representing a Document.
/// A LINQ expression filter.
/// An optional partition key.
public TDocument GetOne(Expression> filter, string partitionKey = null) where TDocument : IDocument
{
return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault();
}
///
/// Returns a collection cursor.
///
/// The type representing a Document.
/// A LINQ expression filter.
/// An optional partition key.
public IFindFluent GetCursor(Expression> filter, string partitionKey = null) where TDocument : IDocument
{
return HandlePartitioned(partitionKey).Find(filter);
}
///
/// Returns true if any of the document of the collection matches the filter condition.
///
/// The type representing a Document.
/// A LINQ expression filter.
/// An optional partition key.
public async Task AnyAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument
{
var count = await HandlePartitioned(partitionKey).CountAsync(filter);
return (count > 0);
}
///
/// Returns true if any of the document of the collection matches the filter condition.
///
/// The type representing a Document.
/// A LINQ expression filter.
/// An optional partition key.
public bool Any(Expression> filter, string partitionKey = null) where TDocument : IDocument
{
var count = HandlePartitioned(partitionKey).Count(filter);
return (count > 0);
}
///
/// Asynchronously returns a list of the documents matching the filter condition.
///
/// The type representing a Document.
/// A LINQ expression filter.
/// An optional partition key.
public async Task> GetAllAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument
{
return await HandlePartitioned(partitionKey).Find(filter).ToListAsync();
}
///
/// Returns a list of the documents matching the filter condition.
///
/// The type representing a Document.
/// A LINQ expression filter.
/// An optional partition key.
public List GetAll(Expression> filter, string partitionKey = null) where TDocument : IDocument
{
return HandlePartitioned(partitionKey).Find(filter).ToList();
}
///
/// Asynchronously counts how many documents match the filter condition.
///
/// The type representing a Document.
/// A LINQ expression filter.
/// An optional partitionKey
public async Task CountAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument
{
return await HandlePartitioned(partitionKey).CountAsync(filter);
}
///
/// Counts how many documents match the filter condition.
///
/// The type representing a Document.
/// A LINQ expression filter.
/// An optional partitionKey
public long Count(Expression> filter, string partitionKey = null) where TDocument : IDocument
{
return HandlePartitioned(partitionKey).Find(filter).Count();
}
#endregion
#region Read TKey
///
/// Asynchronously returns one document given its id.
///
/// The type representing a Document.
/// The type of the primary key for a Document.
/// The Id of the document you want to get.
/// An optional partition key.
public async Task GetByIdAsync(TKey id, string partitionKey = null)
where TDocument : IDocument
where TKey : IEquatable
{
var filter = Builders.Filter.Eq("Id", id);
return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync();
}
///
/// Returns one document given its id.
///
/// The type representing a Document.
/// The type of the primary key for a Document.
/// The Id of the document you want to get.
/// An optional partition key.
public TDocument GetById(TKey id, string partitionKey = null)
where TDocument : IDocument
where TKey : IEquatable
{
var filter = Builders.Filter.Eq("Id", id);
return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault();
}
///
/// Asynchronously returns one document given an expression filter.
///
/// The type representing a Document.
/// The type of the primary key for a Document.
/// A LINQ expression filter.
/// An optional partition key.
public async Task GetOneAsync(Expression> filter, string partitionKey = null)
where TDocument : IDocument
where TKey : IEquatable
{
return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync();
}
///
/// Returns one document given an expression filter.
///
/// The type representing a Document.
/// The type of the primary key for a Document.
/// A LINQ expression filter.
/// An optional partition key.
public TDocument GetOne(Expression> filter, string partitionKey = null)
where TDocument : IDocument
where TKey : IEquatable
{
return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault();
}
///
/// Returns a collection cursor.
///
/// The type representing a Document.
/// The type of the primary key for a Document.
/// A LINQ expression filter.
/// An optional partition key.
public IFindFluent GetCursor(Expression> filter, string partitionKey = null)
where TDocument : IDocument
where TKey : IEquatable
{
return HandlePartitioned(partitionKey).Find(filter);
}
///
/// Returns true if any of the document of the collection matches the filter condition.
///
/// The type representing a Document.
/// The type of the primary key for a Document.
/// A LINQ expression filter.
/// An optional partition key.
public async Task AnyAsync(Expression> filter, string partitionKey = null)
where TDocument : IDocument
where TKey : IEquatable
{
var count = await HandlePartitioned(partitionKey).CountAsync(filter);
return (count > 0);
}
///
/// Returns true if any of the document of the collection matches the filter condition.
///
/// The type representing a Document.
/// The type of the primary key for a Document.
/// A LINQ expression filter.
/// An optional partition key.
public bool Any(Expression> filter, string partitionKey = null)
where TDocument : IDocument
where TKey : IEquatable
{
var count = HandlePartitioned(partitionKey).Count(filter);
return (count > 0);
}
///
/// Asynchronously returns a list of the documents matching the filter condition.
///
/// The type representing a Document.
/// The type of the primary key for a Document.
/// A LINQ expression filter.
/// An optional partition key.
public async Task> GetAllAsync(Expression> filter, string partitionKey = null)
where TDocument : IDocument
where TKey : IEquatable
{
return await HandlePartitioned(partitionKey).Find(filter).ToListAsync();
}
///
/// Returns a list of the documents matching the filter condition.
///
/// The type representing a Document.
/// The type of the primary key for a Document.
/// A LINQ expression filter.
/// An optional partition key.
public List GetAll(Expression> filter, string partitionKey = null)
where TDocument : IDocument
where TKey : IEquatable
{
return HandlePartitioned(partitionKey).Find(filter).ToList();
}
///
/// Asynchronously counts how many documents match the filter condition.
///
/// The type representing a Document.
/// The type of the primary key for a Document.
/// A LINQ expression filter.
/// An optional partitionKey
public async Task CountAsync(Expression> filter, string partitionKey = null)
where TDocument : IDocument
where TKey : IEquatable
{
return await HandlePartitioned(partitionKey).CountAsync(filter);
}
///
/// Counts how many documents match the filter condition.
///
/// The type representing a Document.
/// The type of the primary key for a Document.
/// A LINQ expression filter.
/// An optional partitionKey
public long Count(Expression> filter, string partitionKey = null)
where TDocument : IDocument
where TKey : IEquatable
{
return HandlePartitioned(partitionKey).Find(filter).Count();
}
#endregion
#region Utility Methods
///
/// Gets a collections for the type TDocument with the matching partition key.
///
/// The document type.
/// The partion key.
/// An
protected IMongoCollection GetCollection(string partitionKey) where TDocument : IDocument
{
return MongoDbContext.GetCollection(partitionKey);
}
///
/// Gets a collections for the type TDocument
///
/// The document type.
///
protected IMongoCollection GetCollection() where TDocument : IDocument
{
return MongoDbContext.GetCollection();
}
///
/// Gets a collections for the type TDocument
///
/// The document type.
/// The document.
///
protected IMongoCollection HandlePartitioned(TDocument document) where TDocument : IDocument
{
if (document is IPartitionedDocument)
{
return GetCollection(((IPartitionedDocument)document).PartitionKey);
}
return GetCollection();
}
///
/// Gets a collections for a potentially partitioned document type.
///
/// The document type.
/// The type of the primary key.
/// The document.
///
protected IMongoCollection HandlePartitioned(TDocument document)
where TDocument : IDocument
where TKey : IEquatable
{
if (document is IPartitionedDocument)
{
return GetCollection(((IPartitionedDocument)document).PartitionKey);
}
return GetCollection();
}
///
/// Gets a collections for a potentially partitioned document type.
///
/// The document type.
/// The collection partition key.
///
protected IMongoCollection HandlePartitioned(string partitionKey) where TDocument : IDocument
{
if (!string.IsNullOrEmpty(partitionKey))
{
return GetCollection(partitionKey);
}
return GetCollection();
}
///
/// Gets a collections for the type TDocument with a partition key.
///
/// The document type.
/// The type of the primary key.
/// The collection partition key.
///
protected IMongoCollection GetCollection(string partitionKey)
where TDocument : IDocument
where TKey : IEquatable
{
return MongoDbContext.GetCollection(partitionKey);
}
///
/// Gets a collections for the type TDocument
///
/// The document type.
/// The type of the primary key.
///
protected IMongoCollection GetCollection()
where TDocument : IDocument
where TKey : IEquatable
{
return MongoDbContext.GetCollection();
}
///
/// Gets a collections for a potentially partitioned document type.
///
/// The document type.
/// The type of the primary key.
/// The collection partition key.
///
protected IMongoCollection HandlePartitioned(string partitionKey)
where TDocument : IDocument
where TKey : IEquatable
{
if (!string.IsNullOrEmpty(partitionKey))
{
return GetCollection(partitionKey);
}
return GetCollection();
}
#endregion
}
}