I recently started a small project with a friend and we opted for MongoDB
 as our data store. One of the initial tasks was to write a repository 
class that allowed us to store, retrieve, update and search for entities
 in MongoDB. In the past, I've worked on codebases where there was one 
repository per entity, it didn't take long to discover that this 
resulted in a lot of code duplication across the data layer. So the goal
 here was to write the repository generically enough so that we only 
have one implementation that can be reused for any entity within our 
application. This meant that each entity would have its own MongoDB 
collection (if you're not familiar with MongoDB, a collection can be 
thought of as a table in the relational world - see this page for a comparison).
One of the first steps in this task was to write an interface for the repository - this is in case we decide to use a different data store in the future. A while back, I found a repository interface on the Redmondo blog which covers everything I'd want from a repository, so we'll use a slightly modified version of that interface (I've removed comments for brevity, you can download the code using a link further below and that'll contain the comments):
One of the first steps in this task was to write an interface for the repository - this is in case we decide to use a different data store in the future. A while back, I found a repository interface on the Redmondo blog which covers everything I'd want from a repository, so we'll use a slightly modified version of that interface (I've removed comments for brevity, you can download the code using a link further below and that'll contain the comments):
 public interface IRepository<TEntity> where TEntity : EntityBase
{
bool Insert(TEntity entity);
bool Update(TEntity entity);
bool Delete(TEntity entity);
IList<TEntity>
SearchFor(Expression<Func<TEntity, bool>> predicate);
IList<TEntity> GetAll();
TEntity GetById(Guid id);
}
To paraphrase the code, this is a generic repository interface for an 
entity of type TEntity that must derive from a base class called 
EntityBase. The EntityBase class is a very simple abstract class and 
contains just one property, the identifier property:
{
bool Insert(TEntity entity);
bool Update(TEntity entity);
bool Delete(TEntity entity);
IList<TEntity>
SearchFor(Expression<Func<TEntity, bool>> predicate);
IList<TEntity> GetAll();
TEntity GetById(Guid id);
}
 /// <summary>
/// A non-instantiable base entity which defines
/// members available across all entities.
/// </summary>
public abstract class EntityBase
{
public Guid Id { get; set; }
}
The idea is for any entity that we want to manage in our data store, 
that entity must derive from EntityBase. So the infrastructure is all in
 place for our "MongoDbRepository". I used the official 10gen MongoDB C#
 driver (available as a NuGet package) and arrived at the following repository implementation:
/// A non-instantiable base entity which defines
/// members available across all entities.
/// </summary>
public abstract class EntityBase
{
public Guid Id { get; set; }
}
 /// <summary>
/// A MongoDB repository. Maps to a collection with the same name
/// as type TEntity.
/// </summary>
/// <typeparam name="T">Entity type for this repository</typeparam>
public class MongoDbRepository<TEntity> :
IRepository<TEntity> where
TEntity : EntityBase
{
private MongoDatabase database;
private MongoCollection<TEntity> collection;
 
public MongoDbRepository()
{
GetDatabase();
GetCollection();
}
 
public bool Insert(TEntity entity)
{
entity.Id = Guid.NewGuid();
return collection.Insert(entity).Ok;
}
 
public bool Update(TEntity entity)
{
if (entity.Id == null)
return Insert(entity);
        
return collection
.Save(entity)
.DocumentsAffected > 0;
}
 
public bool Delete(TEntity entity)
{
return collection
.Remove(Query.EQ("_id", entity.Id))
.DocumentsAffected > 0;
}
 
public IList<TEntity>
SearchFor(Expression<Func<TEntity, bool>> predicate)
{
return collection
.AsQueryable<TEntity>()
.Where(predicate.Compile())
.ToList();
}
 
public IList<TEntity> GetAll()
{
return collection.FindAllAs<TEntity>().ToList();
}
 
public TEntity GetById(Guid id)
{
return collection.FindOneByIdAs<TEntity>(id);
}
 
#region Private Helper Methods
private void GetDatabase()
{
var client = new MongoClient(GetConnectionString());
var server = client.GetServer();
 
database = server.GetDatabase(GetDatabaseName());
}
 
private string GetConnectionString()
{
return ConfigurationManager
.AppSettings
.Get("MongoDbConnectionString")
.Replace("{DB_NAME}", GetDatabaseName());
}
 
private string GetDatabaseName()
{
return ConfigurationManager
.AppSettings
.Get("MongoDbDatabaseName");
}
 
private void GetCollection()
{
collection = database
.GetCollection<TEntity>(typeof(TEntity).Name);
}
#endregion
}
In case you're interested, a while ago I wrote a separate blog post
 on how to perform CRUD operations against MongoDB using the C# driver. 
To use the repository implementation, you'll need two application 
configuration settings defined - one that stores the name of the MongoDB
 database and the other that contains the MongoDB connection string 
(with a placeholder for the database name). You should have something 
like:
/// A MongoDB repository. Maps to a collection with the same name
/// as type TEntity.
/// </summary>
/// <typeparam name="T">Entity type for this repository</typeparam>
public class MongoDbRepository<TEntity> :
IRepository<TEntity> where
TEntity : EntityBase
{
private MongoDatabase database;
private MongoCollection<TEntity> collection;
public MongoDbRepository()
{
GetDatabase();
GetCollection();
}
public bool Insert(TEntity entity)
{
entity.Id = Guid.NewGuid();
return collection.Insert(entity).Ok;
}
public bool Update(TEntity entity)
{
if (entity.Id == null)
return Insert(entity);
return collection
.Save(entity)
.DocumentsAffected > 0;
}
public bool Delete(TEntity entity)
{
return collection
.Remove(Query.EQ("_id", entity.Id))
.DocumentsAffected > 0;
}
public IList<TEntity>
SearchFor(Expression<Func<TEntity, bool>> predicate)
{
return collection
.AsQueryable<TEntity>()
.Where(predicate.Compile())
.ToList();
}
public IList<TEntity> GetAll()
{
return collection.FindAllAs<TEntity>().ToList();
}
public TEntity GetById(Guid id)
{
return collection.FindOneByIdAs<TEntity>(id);
}
#region Private Helper Methods
private void GetDatabase()
{
var client = new MongoClient(GetConnectionString());
var server = client.GetServer();
database = server.GetDatabase(GetDatabaseName());
}
private string GetConnectionString()
{
return ConfigurationManager
.AppSettings
.Get("MongoDbConnectionString")
.Replace("{DB_NAME}", GetDatabaseName());
}
private string GetDatabaseName()
{
return ConfigurationManager
.AppSettings
.Get("MongoDbDatabaseName");
}
private void GetCollection()
{
collection = database
.GetCollection<TEntity>(typeof(TEntity).Name);
}
#endregion
}
 <appSettings>
<add key="MongoDbDatabaseName" value="MyCarsDatabase" />
<add key="MongoDbConnectionString"
value="mongodb://localhost/{DB_NAME}?safe=true" />
</appSettings>
Hopefully this repository is useful to someone else who is working with 
MongoDB in C#. Any questions or suggestions for improvements are always 
welcome via comments. <add key="MongoDbDatabaseName" value="MyCarsDatabase" />
<add key="MongoDbConnectionString"
value="mongodb://localhost/{DB_NAME}?safe=true" />
</appSettings>
Sign up here with your email
 
ConversionConversion EmoticonEmoticon