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);
thi开发者_Python百科s.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.
// 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");
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...
}
}
this is also interesting if you want to use repository pattern.
精彩评论