NoSQL, используя MongoDB, NoRM и ASP.NET MVC

Автор оригинала: Shiju Varghese
  • Перевод


В данной статье, я хотел бы рассказать, как работать с NoSQL и документо-ориентированной базой данных MongoDB, NoRM и ASP.NET MVC 2.

NoSQL и документо-ориентированная база данных


В этом году особенно заметны активные движения в направлении NoSQL и люди постоянно обсуждают о применении  документо-ориентированных баз вместе с веб-приложениями. Согласно Википедии “NoSQL — движение, продвигающее свободный класс не реляционных хранилищ данных, которое прервало длинную историю реляционных баз данных.  Данные хранилища могут не требовать фиксированных схем для таблиц, чаще всего избегают join-операций и обычно имеют горизонтальное масштабирование. Преподаватели часто ссылаются на подобные базы данных, как на структурированные хранилища.

Документо-ориентированные базы данных не зависимы от схем, так что вы можете сосредоточится на проблемной предметной области и не волноваться об обновлении схемы во время расширений домена, что позволяет использовать реальный доменно-ориентированный подход при разработке. Одним из основных проблемных мест в реляционных базах данных является синхронизация схемы базы данных с сущностями домена, когда сам домен развивается. На данный момент присутствует огромное количество реализаций NoSQL подхода, но мое внимание больше привлекли CouchDB и MongoDB. Наблюдая за развитием обеих баз данных, я обнаружил, что CouchDB не умеет выполнять динамические запросы, поэтому  позже взял на вооружение MongoDB. Для данной базы в наличии множество драйверов под .NET.

MongoDB


MongoDB является открытым программным обеспечением, расширяемой, высокопроизводительной, свободной от схем, документо-ориентированной базой данных, написанной на C++. Разрабатывается с октября 2007 года компанией 10gen. MonoDB хранит все ваши данные в формате бинарного JSON (BSON). MongoDB привлекает все больше внимания и, как можно увидеть, получил широкое распространение в реальной жизни.

NoRM – C#-драйвер для MongoDB


NoRM является С#-драйвером для MongoDB, поддерживающим LINQ. NoRM проект доступен на Github.

Демонстрация работы с ASP.NET MVC


Я покажу простой пример с использованием MongoDB, NoRM и ASP.NET MVC. Для работы с MongoDB и NoRM проделайте следующие шаги:
  1. Установите MongoDB для 32bit или 64bit версию. Архивы содержат mongodb.exe для запуска сервера и mongo.exe для клиента.
  2. Загрузите драйвер NoRM для MongoDB
  3. Создайте директорию с именем “C:\data\db”. Это стандартное местоположение баз MongoDB.
  4. Запустите MongoDB сервер C:\Mongo\bin\mongod.exe.

Теперь, я собираюсь продемонстрировать, как создать ASP.NET MVC приложение, используя MongoDB и NoRM.

Давайте напишем класс домена.
public class Category
{     
  [MongoIdentifier]
  public ObjectId Id { get; set; }

  [Required(ErrorMessage = "Name Required")]
  [StringLength(25, ErrorMessage = "Must be less than 25 characters")]
  public string Name { get; set;}

  public string Description { get; set; }
}

ObjectId является NoRM типом, который представляет MongoDB ObjectId. NoRM автоматически обновит Id, потому что оснащен атрибутом MongoIdentifier. Следующим шагом будет создание класса MongoSession. Он будет осуществлять любое взаимодействие с MongoDB.
internal class MongoSession<tentity> : IDisposable
{
  private readonly MongoQueryProvider provider;

  public MongoSession()
  {
    this.provider = new MongoQueryProvider("Expense");
  }

  public IQueryable<tentity> Queryable
  {
    get { return new MongoQuery<tentity>(this.provider); }
  }

  public MongoQueryProvider Provider
  {
    get { return this.provider; }
  }

  public void Add<t>(T item) where T : class, new()
  {
    this.provider.DB.GetCollection<t>().Insert(item);
  }

  public void Dispose()
  {
    this.provider.Server.Dispose();
  }

  public void Delete<t>(T item) where T : class, new()
  {
    this.provider.DB.GetCollection<t>().Delete(item);
  }

  public void Drop<t>()
  {
    this.provider.DB.DropCollection(typeof(T).Name);
  }

  public void Save<t>(T item) where T : class,new()
  {
    this.provider.DB.GetCollection<t>().Save(item);     
  }
}

Конструктор MongoSession создаст экземпляр MongoQueryProvider, который поддерживает LINQ выражения, а также создаст базу данных с именем “Expense”. Если же база с таким именем уже присутствует, то он будет использовать уже существующую. Метод Save может быть использован, как для Insert, так и для Update операций. Если объект является новым, то создастся новая запись иначе обновятся данные документа с передаваемым ObjectId.

Давайте создадим ASP.NET MVC контроллер и методы действий для обработки CRUD сценария для класса домена Category.
public class CategoryController : Controller
{

//Index – Получаем список категорий
public ActionResult Index()
{
  using (var session = new MongoSession<category>())
  {
    var categories = session.Queryable.AsEnumerable<category>();
    return View(categories);
  }
}

//Редактируем единственную категорию
[HttpGet]
public ActionResult Edit(ObjectId id)
{
  using (var session = new MongoSession<category>())
  {
    var category = session.Queryable
       .Where(c => c.Id == id)
       .FirstOrDefault();

    return View("Save",category);
  }
}

// GET: /Category/Create
[HttpGet]
public ActionResult Create()
{
  var category = new Category();
  return View("Save", category);
}

//Добавляем или изменяем категорию
[HttpPost]
public ActionResult Save(Category category)
{
  if (!ModelState.IsValid)
  {
    return View("Save", category);
  }
  using (var session = new MongoSession<category>())
  {
    session.Save(category);
    return RedirectToAction("Index");
  }
}

//Удаляем категорию
[HttpPost]
public ActionResult Delete(ObjectId Id)
{
  using (var session = new MongoSession<category>())
  {
    var category = session.Queryable
       .Where(c => c.Id == Id)
       .FirstOrDefault();
    session.Delete(category);
    var categories = session.Queryable.AsEnumerable<category>();
    return PartialView("CategoryList", categories);
  }
}   
}

Как вы видите, вы можете с легкостью работать с MongoDB, используя NoRM в ASP.NET MVC приложениях. Я создал репозиторий на CodePlex, где вы можете загрузить исходный код данного ASP.NET MVC приложения.
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 23

    –6
    No!
      –6
      Как раз искал статью про аспэху, и любую базу кроме мускула! Спасибо!
        –2
        У переводчика есть опыт работы с MongoDB?
          +2
          К сожалению отсутствует, но на текущих выходных появится ;)
            0
            Надеюсь, как результат на хабре появиться статья. Будет здорово, есть в ней будет освящена работа с оперативной памятью, я слышал, что в 32 битной версии есть ограничение в 2 гига) а вся db отображается в память, поэтому интересно узнать правда это или нет. А так же интересно посмотреть на расход памяти, когда db забита под завязку.
              0
              Да, на 32 битах база не более 2 Гб, т.к. используются memory-mapped files.
              Ещё добавлю, что замечен всплеск интереса к аналогичной базе на .NET под названием RavenDB: www.codeproject.com/KB/cs/RavenDBIntro.aspx
          0
          Как в MongoDB обстоят дела с optimistic locking и referential integrity?
          Есть ли возможность индексировать или как-то по-другому ускорять тормозящие запросы?
            0
            Насчет поддержки locking механизмов можно прочитать тут, referential integrity не поддерживается.
              0
              Короче, чтобы другим не копаться, в двух словах:

              1) оптимистический локинг на 1 запись, т.е. бизнес-транзакционности нет (обновить запись дебета одновременно записью кредита — нельзя).
              2) оптимистический локинг на вложенные записи, т.е. при обновлении мастер-записи можно обновить деталь-записи. Можно ли обновить какие-то определенные деталь-записи не загружая их все в память — не сказано.

            +2
            Большая просьба к Вам. Если будете пользоваться новой БД, напишите, пожалуйста, сравнения по скорости выполнения с любой другой. А если замерите (ясное дело, качественно-примерно) количество занимаемой памяти — вообще будет шикарно и моей прищнательности не будет конца в рамках разумного. )
              0
              Может мне кто-нибудь назвать пример задачи, для которой использование NoSQL БД будет предпочтительней/оправдонней, чем реляционной?
                0
                Например, задачи, где часто меняется структура данных, где присутствует неполнота данных. Поддержка схемы БД в актуальном состоянии в таком случае может дорого обходиться.
                +1
                маленький офтоп
                Мы используем активно используем MongoDb в наших проектах — и да, чуть что, системный инженер утерая горькие слезы пырится в лог запросов монги ибо хрен его знает когда эта неведомая херота начнет свопится на диск.=) Это все понятно но вот недавно эта ваша монго вместе со свей этой теткой как там ее Кристина Чудроу(тетка которая у них подписывается под всеми презентациями и корпоративными херями типо саппорта) отожгла ваще неподецки.
                Короче цимес вот в чем ни стого ни с сего в верхнем левом углу появляется надпись «writing more»
                Сломав голову сменив два дебагера мы понимаем что это бля тупо в модуле для php прямо набыдлокожено
                github.com/mongodb/mongo-php-driver/commit/05209bc7a65696203da0fee6d5c2270d7bf303e7
                Да да php_printf(«writing more\n»); прямо в модуле
                Причем челы из монги пока не нашлась именно та самая строчка в исходниках грили что типо они ваще не при делах
                в итоге когда ткнули носом Кристина родила фразу которая стала у нас в компании нарицательной
                Sorry, debugging output.
                jira.mongodb.org/browse/PHP-91
                  0
                  Немного оффтопик.
                  А почему бы вместо
                  var category = session.Queryable
                      .Where(c => c.Id == Id)
                      .FirstOrDefault();


                  не писать
                  var category = session.Queryable
                      .FirstOrDefault(c => c.Id == Id);

                  ?
                  • НЛО прилетело и опубликовало эту надпись здесь
                    0
                    есть вопрос, я так понял вся суть этой штуки в том что в любой момент времени я могу дополнить класс category дополнительными полями и оно все будет нормально работать, то есть мне не нужно будет заморачиваться что там и как будет в базе?

                    и еще один вопрос к знатокам есть ли возможность тащить с апликухой (не веб) standalone базу, чтобы без инсталяторов и всякой другой разности?
                      0
                      мне не нужно будет заморачиваться что там и как будет в базе?

                      Именно так.
                        0
                        Прежде чем бросаться изучать очередную не отлаженную технологию, сначала почитайте про ORM. То, что обычно бизнес-сущности напрямую соответствуют таблицам в базе, еще не значит, что так должно быть всегда.
                          0
                          ну то все понятно, меня вот к примеру больше интересует вариант: при необходимости склепать по быстрому маленькую апликуху которая будет с собой таскать несколько табличек и чем меньше мне для этого надо будет изворачиваться — тем счастливее я буду.

                          до этого делал на winform'ах и xml — не могу сказать что очень доволен, сейчас пытаюсь въехать в wpf — так там сам черт ногу сломит :(

                          а так конечно да, не вопрос, если делать какой ни буть энтерпрайз то надо все по науке и ни шага в сторону…
                            0
                            Так вы почитали или нет?
                            Вот вам другое более ms-ориентированное волшебное слово, раз уж вы к ним так привязались ru.wikipedia.org/wiki/ADO.NET_Entity_Framework
                              0
                              Немного раскрою мысль:
                              если вы ищите в mongodb хранилище где нет сложностей со схемой данных — вам оно не нужно. Лучше используйте старые проверенные технологии.
                              Сейчас ключевые козыри MonoDB в масштабируемости, а не в удобстве.
                          0
                          Если надо тащить standalone — можно брать SQL Server CE, FireBird или SQLite.
                          0
                          Насколько я понимаю, одна из проблем при работе с ДОБД (=документно-ориентированных баз) — отсутствие поиска по каким-либо полям, кроме ключа. Эта проблема решается построением индекса. Иногда вручную, иногда при первом запросе (а как с этим у MongoDB?).

                          Другая проблема: данные в ДОБД денормализованы, поэтому чтобы изменить, например, название категории продукта, нужно найти все продукты и поменять это название в них.

                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                          Самое читаемое