Единица работы в mongodb и C #

Я знаю, что MongoDB не должен поддерживать единицу работы и т. д. Но я думаю, что было бы неплохо реализовать репозиторий, в котором будут храниться только намерения (аналогично критериям), а затем зафиксировать их в БД. В противном случае в каждом методе в вашем репозитории вам необходимо создать соединение с БД, а затем закрыть его. Если мы помещаем соединение с БД в какой-то класс BaseRepository, тогда мы привязываем наш репозиторий к конкретной БД, и действительно сложно тестировать репозитории, тестировать IoC, который разрешает репозитории.

Является ли создание сеанса в 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();
        }
    }
28
задан Yurii Hohan 23 August 2011 в 12:21
поделиться

1 ответ

Не беспокойтесь об открытии и закрытии соединений. Драйвер MongoDB C # поддерживает внутренний пул соединений, поэтому вы не будете страдать от затрат на открытие и закрытие реальных соединений каждый раз, когда создаете новый объект MongoServer.

Вы можете создать интерфейс репозитория, который предоставляет вашу логику данных, и построить реализацию MongoDB, которая будет внедрена там, где это необходимо. Таким образом, специальный код подключения MongoDB удаляется от вашего приложения, которое видит только IRepository.

Будьте осторожны, пытаясь реализовать шаблон типа единицы работы с MongoDB. В отличие от SQL Server, в транзакцию нельзя включить несколько запросов, которые можно откатить в случае сбоя.

Простой пример шаблона репозитория с реализациями MongoDB, SQL Server и JSON можно найти в коде хранилища NBlog . Он использует Autofac IoC для внедрения конкретных репозиториев в приложение ASP.NET MVC.

18
ответ дан 28 November 2019 в 03:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: