Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Repository Pattern with MongoDB: Where to initialize the Database

I just started to play around with MongoDB (C#) and tried to port a repository over from entity framework. I'm using the official C# driver 1.0. Now I did something like this:

internal class MongoContext
{
    public MongoContext(string constring)
    {
        MongoServer server = MongoServer.Create(constring);
        this.myDB = server.GetDatabase("MyDB");

        BsonClassMap.RegisterClassMap<VoyageNumber>(cm =>
            { cm.MapField<string>(p => p.Id); });
        BsonClassMap.RegisterClassMap<Schedule>(cm =>
        { cm.MapField<DateTime>(p => p.EndDate); cm.MapField<DateTime>(p => p.StartDate); });
        BsonClassMap.RegisterClassMap<Voyage>(cm =>
            { cm.MapIdField<VoyageNumber>(p => p.VoyageNumber); cm.MapField<Schedule>(p => p.Schedule); });

    }

    private MongoDatabase myDB;
    public MongoDatabase MyDB
    { get { return this.myDB; } }
}

I'd then go on and implement the Repository like this:

public class MongoVoyageRepository : IVoyageRepository
{
    private readonly MongoContext context;

    public MongoVoyageRepository(string constring)
    {
        this.context = new MongoContext(constring);
    }

    public void Store(Domain.Model.Voyages.Voyage voyage)
    {

        MongoCollection<Voyage> mongoVoyages = context.MyDB.GetCollection<Voyage>("Voyages");

        //store logic...

    }

}

Now I'd like to know if it is a good decision to instantiate a "context" like this in terms of performance. Does it make sense to put the BsonClass Maps in there? Thank you for your input.

like image 878
hoetz Avatar asked Apr 10 '11 11:04

hoetz


2 Answers

// entity base
public class MongoEntity {
    public ObjectId _id { get; set; }
}

//user entity
public class Users : MongoEntity {
    public string UserName { get; set; }
    public string Password { get; set; }
}


// simple repository
public class Repository {

    private MongoDatabase _db;
    public MongoDatabase Database { get; private set; }
    public Repository(string constr, string dbname) {
        var server = MongoServer.Create(constr);
        _db = server.GetDatabase(dbname);
        Database = _db;
    }

    private MongoCollection<T> GetCollection<T>() where T : MongoEntity {
        return _db.GetCollection<T>(typeof(T).Name);
    }

    public IEnumerable<T> List<T>() where T : MongoEntity {
        return GetCollection<T>().FindAll();
    }

    public IEnumerable<T> List<T>(Expression<Func<T, bool>> exp) where T : MongoEntity {
        return GetCollection<T>().AsQueryable<T>().Where(exp);
    }

    public T Single<T>(Expression<Func<T, bool>> exp) where T : MongoEntity {
        return List<T>(exp).SingleOrDefault();
    }

    public void Insert<T>(T entity) where T : MongoEntity {
        GetCollection<T>().Insert<T>(entity);
    }

    public void Insert<T>(ICollection<T> entities) where T : MongoEntity {
        GetCollection<T>().InsertBatch(entities);
    }

    // Update, Delete method etc ...



}



// example
var repository = new Repository("mongodb://localhost", "test");
repository.Single<Users>(u => u.UserName == "myUserName");
like image 147
Ebubekir Dirican Avatar answered Nov 15 '22 13:11

Ebubekir Dirican


I guess it does not make sense to register classes mapping each time when you create your repository class. Since MongoDB C# driver manages connections to the MongoDB internally, it seems to me that it's better to create MongoServer and register classes mapping only once, during application start and then use it.

I am using singleton in order to create MongoServer only once

public class MongoRead : MongoBase
{
  public MongoRead(MongoServer server)
            : base(server)
  {

  }


  public override MongoDatabase Database
  {
     get { return Server.GetDatabase("myDb"); }
  }

  public MongoCollection Logs
  {
    get { return Database.GetCollection("logs"); }
  }

  private static MongoRead _instance = null;

  public static MongoRead Instance
  {
    get
      {
        if (_instance == null)
        {
          _instance = RegisterMongoDb();

        }

        return _instance;
      }

  }

  private static MongoRead RegisterMongoDb()
  {
      var readServer = MongoServer.Create(connectionString);
      var read = new MongoRead(readServer);

      var myConventions = new ConventionProfile();
      myConventions.SetIdMemberConvention(new NoDefaultPropertyIdConvention());
      BsonClassMap.RegisterConventions(myConventions, t => true);

      return read;
  }

}

So you also can use above class in your Repository:

public class MongoVoyageRepository : IVoyageRepository
{
    private readonly MongoRead context
    {
      get { return MongoRead.Instance; }
    };

    public MongoVoyageRepository()
    {
    }

    public void Store(Domain.Model.Voyages.Voyage voyage)
    {
            MongoCollection<Voyage> mongoVoyages = 
                  context.Database.GetCollection<Voyage>("Voyages");
            //store logic...
    }

}
like image 20
Andrew Orsich Avatar answered Nov 15 '22 13:11

Andrew Orsich