Я знаю, что MongoDB не должен поддерживать единицу работы и т. Д. Но я думаю, что было бы неплохо реализовать репозиторий, в котором будут храниться только намерения (похожие на критерии), а затем зафиксировать их в БД. В противном случае в каждом методе вашего репозитория вам необходимо создать соединение с БД, а затем закрыть его. Если мы поместим соединение с БД в некоторый класс BaseRepository, то мы привяжем наш репозиторий к конкретному БД, и действительно сложно протестировать репозитории, чтобы проверить IoC, которые разрешают репозитории.Единица работы в mongodb и C#
Создает ли сеанс в MongoDB плохую идею? Есть ли способ отделить логику соединения от хранилища?
Вот код Коури Роб. Это хорошая идея всегда подключаться к вашей БД по каждому запросу? Какова наилучшая практика?
Есть еще одна вещь. Представьте, что я хочу предоставить индекс для коллекции. Раньше я делал это в конструкторе, но с подходом Роба это кажется логичным, чтобы сделать это там.
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();
}
}
Как насчет инъекции зависимостей через каркас (или самонаписанный)? – DrColossos
@DrColossos, На самом деле я использую структуру под названием Castle.Windsor. Я видел некоторый код Rob Conery, имитирующий сеансы, но он подключается к БД при каждом создании/обновлении/удалении/поиске, и я не делаю, если это оптимально. –