Подтвердить что ты не робот

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

Я знаю, что 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();
        }
    }
4b9b3361

Ответ 1

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

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

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

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

Ответ 2

Если вы заинтересованы в реализации, похожей на код хранения Rob Connery и NBlog, но используя драйвер mshodp csharp 2.0 (который является асинхронным), вы можете посмотреть:

https://github.com/alexandre-spieser/mongodb-generic-repository

Затем вы можете написать собственный репозиторий, наследующий от BaseMongoRepository.

public interface ITestRepository : IBaseMongoRepository
{
    void DropTestCollection<TDocument>();
    void DropTestCollection<TDocument>(string partitionKey);
}

public class TestRepository : BaseMongoRepository, ITestRepository
{
    public TestRepository(string connectionString, string databaseName) : base(connectionString, databaseName)
    {
    }

    public void DropTestCollection<TDocument>()
    {
        MongoDbContext.DropCollection<TDocument>();
    }

    public void DropTestCollection<TDocument>(string partitionKey)
    {
        MongoDbContext.DropCollection<TDocument>(partitionKey);
    }
}

Ответ 3

При исследовании шаблонов проектирования я создавал базовый шаблон репозитория для .Net Core и MongoDB. Читая документацию MongoDB, я наткнулся на статью о транзакциях в MongoDB. В статье указано, что:

Начиная с версии 4.0, MongoDB предоставляет возможность выполнять многодокументные транзакции с наборами реплик.

Просматривая интертубы, я наткнулся на библиотеку, которая действительно хорошо справляется с реализацией шаблона Unit of Work для MongoDB.