Skip to content

Instantly share code, notes, and snippets.

@pwelter34
Last active December 12, 2015 06:48
Show Gist options
  • Save pwelter34/4731606 to your computer and use it in GitHub Desktop.
Save pwelter34/4731606 to your computer and use it in GitHub Desktop.
MongoDB Repository
public class MongoRepository<TEntity>
where TEntity : class
{
private static readonly Lazy<string> _collectionName;
private static int _mappingInitialized = 0;
private static int _indexingInitialized = 0;
private readonly Lazy<MongoCollection<TEntity>> _collection;
private readonly MongoUrl _mongoUrl;
static MongoRepository()
{
_collectionName = new Lazy<string>(() => typeof(TEntity).Name);
}
public MongoRepository(string connectionName)
: this(GetMongoUrl(connectionName))
{
}
public MongoRepository(MongoUrl mongoUrl)
{
if (mongoUrl == null)
throw new ArgumentNullException("mongoUrl");
_mongoUrl = mongoUrl;
_collection = new Lazy<MongoCollection<TEntity>>(CreateCollection);
}
public MongoCollection<TEntity> Collection
{
get
{
return _collection.Value;
}
}
public TEntity FindById(string id)
{
if (id == null)
throw new ArgumentNullException("id");
var value = ConvertId(id);
return _collection.Value
.FindOneByIdAs<TEntity>(value);
}
public TEntity FindOne(Expression<Func<TEntity, bool>> criteria)
{
if (criteria == null)
throw new ArgumentNullException("criteria");
return _collection.Value
.AsQueryable()
.Where(criteria)
.FirstOrDefault();
}
public IQueryable<TEntity> FindAll(Expression<Func<TEntity, bool>> criteria)
{
if (criteria == null)
throw new ArgumentNullException("criteria");
return _collection.Value
.AsQueryable()
.Where(criteria);
}
public IQueryable<TEntity> All()
{
return _collection.Value.AsQueryable();
}
public TEntity Insert(TEntity entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
BeforeInsert(entity);
_collection.Value.Insert<TEntity>(entity);
return entity;
}
public void Insert(IEnumerable<TEntity> entities)
{
if (entities == null)
throw new ArgumentNullException("entities");
entities.ForEach(e => Insert(e));
}
public void InsertBatch(IEnumerable<TEntity> entities)
{
if (entities == null)
throw new ArgumentNullException("entities");
entities.ForEach(BeforeInsert);
_collection.Value.InsertBatch<TEntity>(entities);
}
public TEntity Update(TEntity entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
BeforeUpdate(entity);
_collection.Value.Save<TEntity>(entity);
return entity;
}
public void Update(IEnumerable<TEntity> entities)
{
if (entities == null)
throw new ArgumentNullException("entities");
entities.ForEach(e => Update(e));
}
public void Delete(string id)
{
if (id == null)
throw new ArgumentNullException("id");
var value = ConvertId(id);
_collection.Value.Remove(Query.EQ("_id", value));
}
public void DeleteAll()
{
_collection.Value.RemoveAll();
}
public long Count()
{
return _collection.Value.Count();
}
public bool Exists(Expression<Func<TEntity, bool>> criteria)
{
if (criteria == null)
throw new ArgumentNullException("criteria");
return _collection.Value
.AsQueryable()
.Any(criteria);
}
public IDisposable RequestStart()
{
return _collection.Value.Database.RequestStart();
}
public void RequestDone()
{
_collection.Value.Database.RequestDone();
}
protected virtual void BeforeUpdate(TEntity entity)
{
}
protected virtual void BeforeInsert(TEntity entity)
{
}
public static string NewId()
{
return ObjectId.GenerateNewId().ToString();
}
protected virtual BsonValue ConvertId(string id)
{
if (id == null)
throw new ArgumentNullException("id");
return ObjectId.Parse(id);
}
protected virtual string GetCollectionName()
{
return _collectionName.Value;
}
protected virtual MongoCollection<TEntity> CreateCollection()
{
CreateMapping();
var client = new MongoClient(_mongoUrl);
var server = client.GetServer();
var database = server.GetDatabase(_mongoUrl.DatabaseName);
string collectionName = GetCollectionName();
var mongoCollection = database.GetCollection<TEntity>(collectionName);
CreateIndexes(mongoCollection);
return mongoCollection;
}
private void CreateMapping()
{
// only initialize mapping once per application life cycle.
if (Interlocked.CompareExchange(ref _mappingInitialized, 1, 0) != 0)
return;
BsonClassMap.RegisterClassMap<TEntity>(CreateMapping);
}
protected virtual void CreateMapping(BsonClassMap<TEntity> classMap)
{
classMap.AutoMap();
var idMember = classMap.GetMemberMap("Id")
.SetRepresentation(BsonType.ObjectId)
.SetIdGenerator(StringObjectIdGenerator.Instance);
classMap.SetIdMember(idMember);
}
private void CreateIndexes(MongoCollection<TEntity> mongoCollection)
{
// only initialize indexes once per application life cycle.
if (Interlocked.CompareExchange(ref _indexingInitialized, 1, 0) != 0)
return;
EnsureIndexes(mongoCollection);
}
protected virtual void EnsureIndexes(MongoCollection<TEntity> mongoCollection)
{
}
private static MongoUrl GetMongoUrl(string connectionName)
{
if (connectionName == null)
throw new ArgumentNullException("connectionName");
var settings = ConfigurationManager.ConnectionStrings[connectionName];
if (settings == null)
throw new ConfigurationErrorsException(
"No connection string named '{0}' could be found in the application configuration file.".FormatWith(
connectionName));
string connectionString = settings.ConnectionString;
if (connectionString.IsNullOrEmpty())
throw new ConfigurationErrorsException(
"The connection string '{0}' in the application's configuration file does not contain the required connectionString attribute.".FormatWith(
connectionName));
var mongoUrl = new MongoUrl(settings.ConnectionString);
return mongoUrl;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment