I am using mongo in my app and have setup a repository pattern with the mongo db connection as a session object. Works great so not quite sure what the question is!
The repository by nature is coupled to mongo and I can't see a non contrived way of testing the repo without connecting to a mongo instance. So I have a test mongo session class which uses a different test db to the main session used for prod. I then have behaviour tests that write to mongo and then inspect mongo to check state. This is not considered good test practise as I end up using multiple pieces of repo functionality to insert then verify, but again I don't see a non contrivied alternative. This is at least easy to do, including clear down between tests as we don't have to worry about schema setup etc. Nor constraints etc.
Be interested in alternatives, but I find a lot of test experts lose touch with reality when they describe how to integration test repositories!
Regarding your life time question, are you writing an app or web site? I'm using asp.net and repositories (and by implication fresh sessions which are injected into repository constrictors) are created on every request and passed into the controllers constructor by ioc. This is standard practise for database access so don't see why mongo approach would be different? Remember here we don't have to do what an orm does in terms of managing a change set. Mongo is much lower level, especially if you want to work atomically.
Index is interesting one. I'm not sure there. Definitey not per session, but not sure what happens if one tries to create an index when collection not yet defined. If it works then I'd be inclined to do a 1 time setup script. If not, maybe a static constructor on repositories to do it one time per app domain?
> I know that MongoDB is not supposed to support unit of work, etc. But
> I think it would be nice to implement the repository which would store
> only the intentions (similar to criteria) and then commit them to the
> DB. Otherwise in every method in your repository you have to create
> connection to DB and then close it. If we place the connection to DBwriting
> in some BaseRepository class, then we tie our repository to concrete
> DB and it is really difficult to test repositories, to test IoC which
> resolve repositories.
> Is creating a session in MongoDB a bad idea? Is there a way to
> separate the connection logic from repository?
> Here is some code by Rob Conery using NORM. Is it a good idea to
> always connect to your DB on every request? What is the best practice?
> There is one more thing. Imagine I want to provide an index for a
> collection. Previously I did in a constructor but with Rob's approach
> this seems out of logic to do it there.
> using Norm;
> using Norm.Responses;
> using Norm.Collections;
> using Norm.Linq;
> public class MongoSession {
> private string _connectionString;
> public MongoSession() {
> //set this connection as you need. This is left here as an
> example, but you could, if you wanted,
> _connectionString = "mongodb://127.0.0.1/MyDatabase?
> strict=false";
> }
> public void
> Delete<T>(System.Linq.Expressions.Expression<Func<T, bool>>
> expression) where T : class, new() {
> //not efficient, NoRM should do this in a way that sends a
> single command to MongoDB.
> var items = All<T>().Where(expression);
> foreach (T item in items) {
> Delete(item);
> }
> }
> public void Delete<T>(T item) where T : class, new() {
> using(var db = Mongo.Create(_connectionString))
> {
> db.Database.GetCollection<T>().Delete(item);
> }
> }
> public void DeleteAll<T>() where T : class, new() {
> using(var db = Mongo.Create(_connectionString))
> {
> db.Database.DropCollection(typeof(T).Name);
> }
> }
> public T Single<T>(System.Linq.Expressions.Expression<Func<T,
> bool>> expression) where T : class, new() {
> T retval = default(T);
> using(var db = Mongo.Create(_connectionString))
> {
> retval = db.GetCollection<T>().AsQueryable()
> .Where(expression).SingleOrDefault();
> }
> return retval;
> }
> public IQueryable<T> All<T>() where T : class, new() {
> //don't keep this longer than you need it.
> var db = Mongo.Create(_connectionString);
> return db.GetCollection<T>().AsQueryable();
> }
> public void Add<T>(T item) where T : class, new() {
> using(var db = Mongo.Create(_connectionString))
> {
> db.GetCollection<T>().Insert(item);
> }
> }
> public void Add<T>(IEnumerable<T> items) where T : class,
> new() {
> //this is WAY faster than doing single inserts.
> using(var db = Mongo.Create(_connectionString))
> {
> db.GetCollection<T>().Insert(items);
> }
> }
> public void Update<T>(T item) where T : class, new() {
> using(var db = Mongo.Create(_connectionString))
> {
> db.GetCollection<T>().UpdateOne(item, item);
> }
> }
> //this is just some sugar if you need it.
> public T MapReduce<T>(string map, string reduce) {
> T result = default(T);
> using(var db = Mongo.Create(_connectionString))
> {
> var mr = db.Database.CreateMapReduce();
> MapReduceResponse response =
> mr.Execute(new MapReduceOptions(typeof(T).Name) {
> Map = map,
> Reduce = reduce
> });
> MongoCollection<MapReduceResult<T>> coll =
> response.GetCollection<MapReduceResult<T>>();
> MapReduceResult<T> r = coll.Find().FirstOrDefault();
> result = r.Value;
> }
> return result;
> }
> public void Dispose() {
> _server.Dispose();
> }
> }