Комплексное таксономическое картирование ORM - ищем предложения - PullRequest
1 голос
/ 09 февраля 2011

В моем проекте (ASP.NET MVC + NHibernate) у меня есть все мои сущности, скажем, Document s, описанные набором пользовательских метаданных. Метаданные содержатся в структуре, которая может иметь несколько тегов, категорий и т. Д. Эти термины имеют наибольшее значение для пользователей, ищущих нужный документ, поэтому они влияют на представления, а также на базовые структуры данных, запросы к базе данных и т. Д.

С точки зрения приложения, меня больше всего интересуют строковые значения для терминов. В идеале я хотел бы работать непосредственно с коллекциями строк следующим образом:

class MetadataAsSeenInViews
{
    public IList<string> Categories;
    public IList<string> Tags;
    // etc.
}

С точки зрения модели, я мог бы использовать ту же структуру, сделать максимально простое сопоставление ORM и использовать его в запросах типа «получить все документы с метаданными точно так же, как это».

Но такая структура может оказаться бесполезной, если приложению необходимо выполнить сложные запросы к базе данных, такие как «получить все документы, для которых , по крайней мере, одна категорий равна IN (cat1, cat2, ..., catN) ИЛИ, по крайней мере, один тегов равен IN (tag1, ..., tagN) ". В этом случае по соображениям производительности мы, вероятно, будем использовать цифровые клавиши для категорий и тегов.

Таким образом, можно представить структуру, противоположную MetadataAsSeenInViews, которая работает с числовыми ключами и обеспечивает сложные отображения целых чисел в строки и наоборот. Но это решение меня не устраивает по нескольким причинам:

  • пахнет как нарушение единственной ответственности, поскольку мы имеем дело с проблемами, связанными с базой данных, когда просто хотим описать Document бизнес-объект
  • ключи базы данных просачиваются через все слои
  • добавляет ненужные сложности в представления
  • и я считаю, что это не использует то, что может сделать хороший ORM

В идеале я хотел бы иметь:

  • единичная, как можно более простая структура метаданных (в идеале, подобная той, что вверху) во всем приложении
  • сложные проблемы запросов, решаемые только на уровне базы данных (имеется в виду DB + ORM + при минимально возможном дополнительном коде для уровня данных)

Есть ли у вас какие-либо идеи о том, как структурировать код и сделать ли сопоставления ORM настолько элегантными, эффективными и настолько производительными, насколько это возможно?

Ответы [ 2 ]

0 голосов
/ 18 февраля 2011

Решение, которое я наконец-то реализовал, не полностью удовлетворяет меня, но к настоящему моменту оно будет удовлетворено.

Я разделил свои теги / категории на "реальные объекты", отображенные в NHibernate как отдельныесущности и «ссылки», отображаемые как компоненты в зависимости от сущностей, которые они описывают.

Так что в моем коде C # у меня есть два отдельных класса - TagEntity и TagReference, которые оба несут одну и ту же информацию, если смотреть с точки зрения предметной области.TagEntity знает идентификатор базы данных и управляется сессиями NHibernate, тогда как TagReference переносит только имя тега в виде строки, поэтому его очень удобно использовать во всем приложении, а при необходимости его можно легко преобразовать в TagEntity с помощью статического поискасловарь.

Такое разделение сущностей и ссылок позволяет мне более эффективно запрашивать базу данных, объединяя только две таблицы, например select from articles join articles_tags ... where articles_tags.tag_id = X, без присоединения к таблице tags, которая также будет объединена при выполнении простого полностью-объектно-ориентированные запросы NHibernate.

0 голосов
/ 10 февраля 2011

Я обнаружил, что проблематично использовать доменные объекты непосредственно в представлениях. Чтобы помочь развязать вещи, я применяю два разных метода.

Самое главное, я использую отдельные классы ViewModel для передачи данных в представления. Когда данные хорошо соответствуют сущности модели предметной области, AutoMapper может облегчить копирование данных между ними, но в противном случае требуется немного ручного подключения. Похоже, что вначале много работы, но она действительно помогает, когда проект начинает расти, и это особенно важно, если вы только что создали базу данных с нуля. Я также использую промежуточный сервисный уровень для получения ViewModels, чтобы поддерживать стройность контроллеров и возможность повторного использования логики.

Второй вариант в основном из соображений производительности, но я обычно заканчиваю созданием пользовательских репозиториев для извлечения данных, охватывающих сущности. То есть я создаю собственный класс для хранения данных, которые мне интересны, а затем пишу собственный LINQ (или любой другой) для проецирования результата в него. Это часто может значительно повысить производительность по сравнению с простым извлечением объектов и применением проекции после извлечения данных.

Дайте мне знать, если я недостаточно тщательно проработал.

...