Skip to content

Instantly share code, notes, and snippets.

@antdimot
Last active July 7, 2022 23:59
Show Gist options
  • Save antdimot/5037532 to your computer and use it in GitHub Desktop.
Save antdimot/5037532 to your computer and use it in GitHub Desktop.
Example of mongodb repository in C#
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
using MongoDB.Driver.Linq;
namespace PRJ.Data
{
public class Repository<T> where T : IEntity<ObjectId>
{
DataContext _context;
MongoCollection<T> _collection;
public MongoCollection<T> Collection { get { return _collection; } }
public Repository( DataContext context )
{
_context = context;
_collection = _context.GetDatabase().GetCollection<T>( typeof( T ).Name.ToLower() );
}
private IQueryable<T> CreateSet()
{
return _collection.AsQueryable<T>();
}
public T Insert( T instance )
{
try
{
instance.Id = ObjectId.GenerateNewId();
_collection.Insert<T>( instance );
return instance;
}
catch( Exception ex )
{
//todo: handle exception
throw ex;
}
}
public void Update( T instance )
{
try
{
var query = Query<T>.EQ( o => o.Id, instance.Id );
var update = Update<T>.Replace( instance );
_collection.Update( query, update );
}
catch( Exception ex )
{
//todo: handle exception
throw ex;
}
}
public void Delete( ObjectId id, bool logical = true )
{
try
{
if( logical )
{
_collection.Update(
Query<T>.EQ<ObjectId>( p => p.Id, id ),
Update<T>.Set<bool>( p => p.Deleted, true ) );
}
else
{
_collection.Remove( Query<T>.EQ<ObjectId>( p => p.Id, id ) );
}
}
catch( Exception ex )
{
//todo: handle exception
throw ex;
}
}
public T GetById( ObjectId id )
{
return this.Single( o => o.Id == id );
}
public T Single( Expression<Func<T, bool>> predicate = null )
{
var set = CreateSet();
var query = ( predicate == null ? set : set.Where( predicate ) );
return query.SingleOrDefault();
}
public IReadOnlyList<T> List( Expression<Func<T, bool>> condition = null, Func<T, string> order = null )
{
var set = CreateSet();
if( condition != null )
{
set = set.Where( condition );
}
if( order != null )
{
return set.OrderBy( order ).ToList();
}
return set.ToList();
}
public int Count( Expression<Func<T, bool>> predicate = null )
{
var set = CreateSet();
return ( predicate == null ? set.Count() : set.Count( predicate ) );
}
public bool Exists( Expression<Func<T, bool>> predicate )
{
var set = CreateSet();
return set.Any( predicate );
}
}
public class DataContext
{
string _mongoServerUrl;
string _mongoDbName;
MongoClient _client;
public DataContext( string dburl, string dbname )
{
_mongoServerUrl = dburl;
_mongoDbName = dbname;
_client = new MongoClient( _mongoServerUrl );
}
public MongoDatabase GetDatabase() { return _client.GetServer().GetDatabase( _mongoDbName ); }
public void DropDatabase( string dbName )
{
var server = _client.GetServer();
server.DropDatabase( dbName );
}
public void DropCollection<T>() where T : IEntity<ObjectId>
{
var database = GetDatabase();
var collectionName = typeof( T ).Name.ToLower();
if( database.CollectionExists( collectionName ) )
{
database.DropCollection( collectionName );
}
}
}
public interface IEntity<T>
{
T Id { get; set; }
bool Deleted { get; set; }
}
}
@MahdiKarimipour
Copy link

What would you do with aggregations? I believe you only support composition, meaning objects contain the whole objects inside them, instead of keeping a reference inside. Is that right?

@antdimot
Copy link
Author

Hi bprhw, 'CreateNotdeletedSet()' was a refuse of an old code. I just updated it.

Sorry for delay of the answer :)

@antdimot
Copy link
Author

Hi Mahadi-K, you are right this example provides only composition support. I'm not sure that could be useful to have a reference to object when i'm working with non relational approach.

@Skrappy
Copy link

Skrappy commented Jul 14, 2015

Hi antdimot, these code snippets are exactly what I was looking for.... Do you have a sample project where this pattern is implemented? Maybe in a WebApi?

@antdimot
Copy link
Author

Hi @ Skrappy , I have just released a project that use it.

gstore

@ryzhkovAndruha
Copy link

I don't understand why do you need "Deleted" property in IEntity.

@antdimot
Copy link
Author

antdimot commented May 1, 2020

I don't understand why do you need "Deleted" property in IEntity.

Its for logical delete only.

@okutbay
Copy link

okutbay commented Sep 23, 2020

Hi @antdimot. I just wonder, in your DataContext class you have a private var called _mongoDbName and you are setting it within the constructor.
Then for the "DropDatabase" method you are getting dbname as a parameter which may be out of db context. What is the purpose? Thanks.

@antdimot
Copy link
Author

You are right. The DataContext should not able to drop the database.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment