Архитектура ORM - PullRequest
       2

Архитектура ORM

2 голосов
/ 12 марта 2012

Предыстория: у меня есть проект, который совсем не масштабный (2 веб-приложения ASP.NET по 10 страниц в каждом). Эти два веб-приложения имеют много внутренних требований, в частности, возможность манипулировать набором из 50 таблиц. Они оба используют одну и ту же СУБД, которая всегда будет MySQL.

Проблема: Некоторое время назад в проект была добавлена ​​большая многофункциональная библиотека ORM (Subsonic), которая оказалась слишком большой. Он слишком большой, слишком много деталей, слишком много накладных расходов. Некоторым коллекциям, которые генерируются Subsonic, требуется более 1 минуты для создания, тогда как необработанные встроенные запросы (плохо я знаю), которые выполняют то же самое, требуют ~ 2 с. Проблема не только в Subsonic, NHibernate и другие инструменты ORM просто слишком велики со слишком большим количеством функций, которые никогда не будут использоваться. Масштаб этих проектов также никогда не станет огромным. Кроме того, нет необходимости в агностицизме базы данных, поскольку мы никогда не откажемся от MySQL, и никто никогда не будет использовать этот инструмент, кроме как для внутреннего использования.

Очевидно, что встраивание запросов - это плохо, небезопасно, неправильно. Linq тоже не вариант. Таким образом, существует необходимость в небольшом пользовательском инструменте ORM для упаковки в библиотеке. Моя мысль состоит в том, чтобы включить:

  • Основой является класс Table, в конструктор которого просто передаются имя базы данных и имя таблицы
  • Класс Table публично предоставил бы несколько методов
  • public DataRow Record (строка primaryKeyValue) // извлекает отдельные записи
  • public DataRowCollection Records (строка whereClauseOrRangeOfKeyValues) // извлекает коллекцию записей
  • public bool Save () // сохранить текущее состояние базы данных путем обновления / вставки любых строк, которые изменились; Не уверен, что лучший способ сохранить, какие записи грязные или нет
  • public bool Loaded (string primaryKeyValue) // сообщает, существует ли данная запись или нет
  • public DataRowCollection Query (строка mysqlQuery); // запускаем определенный пользовательский запрос
  • в частном порядке было бы всего лишь несколько вещей: дезинфицирующее средство, метод для выбора, метод для выполнения upserts и ничего больше

Возможно, объединенные знания StackOverflow могут выделить недостатки этой базовой настройки или предложить улучшения. Заранее спасибо.

РЕДАКТИРОВАТЬ: Одно ограничение (не уверен, насколько оно устойчиво на данный момент) заключается в том, что я не использовал готовую библиотеку. Subsonic настолько отключает более высокие взлеты, что любая сторонняя утилита может быть отклонена. Так что это скорее выбор архитектуры, чем выбор утилиты.

Ответы [ 5 ]

6 голосов
/ 12 марта 2012

Прежде чем приступить к созданию собственного инструмента, вы должны проверить микро ORM, например:

А там немного других.

3 голосов
/ 12 марта 2012

Вы действительно не хотите работать с DataRow, если вы не генерируете действительно нестандартные запросы.И вы абсолютно не должны «дезинфицировать» ваши запросы: вместо этого используйте параметры.В общем, это так просто, как return db.SetCommand("SELECT * FROM Person").ExecuteList<Person>();

2 голосов
/ 12 марта 2012

Почему бы не попробовать какую-нибудь микроорганизм, например Dapper.Net (Stackoverflow orm, кстати).Микроформы довольно легки и производительны.Хотя вы должны быть уверены, что он будет работать с MySQL.

1 голос
/ 26 октября 2012

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

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

  • . В своем «базовом» режиме он представляет собой динамическую связь с заданной базой данных, что означает, что вы имеете полную свободу для написания любого запроса или команды к нему и извлечениядает в результате простые в использовании динамические записи.
  • В своем режиме «карт» он предоставляет Entity Framework, специально предназначенную для работы с объектами POCO, так что вам не нужно каким-либо образом изменять ваши классы, ипросто думайте об объектах, а не о вещах, связанных с базой данных.
1 голос
/ 12 марта 2012

Проблема с вашей настройкой заключается в том, что она просто не решает проблему под рукой. Что, кстати, является одной из проблем с большинством ОРМ.

Например:

Допустим, у вас есть таблица Projects, и вам нужно получить список проектов, статус которых Active. Вам не нужны / не нужны все поля, только название проекта, статус, дата начала и дата последнего обновления.

Как вам этого добиться в вашем макете? С самого начала ваш класс таблицы не будет работать (требуются только соединение и имя таблицы), потому что он потребует, чтобы вы извлекли все столбцы: с этой проблемой вы уже столкнулись.

Что означает, что вы должны использовать свой метод Query, чтобы получить именно то, что вы хотите ... Однако, как table узнает, что можно изменить только столбец состояния одной строки при вызове .Save()? Теперь вы становитесь действительно сложным, потому что для выполнения этого требуется еще один пользовательский запрос. Или, по крайней мере, вам придется внедрить отслеживание изменений в каждом столбце, и ваш engine будет достаточно умен, чтобы обновлять только те значения, которые изменились.

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


Итак, что вы будете делать? Мое мнение таково, что вам нужно разделить типы доступа к данным, которые вы делаете, на два логических набора операций. Один набор будет включать в себя наличие регулярных ООП-классов для проверки и обеспечения правильного функционирования ваших бизнес-правил. Они будут использоваться при создании новых записей.

Для следующего набора вы можете использовать простые DataTables или динамические классы. Отправьте запрос в базу данных и извлеките нужные записи. Всякий раз, когда вы делаете обновление, убедитесь, что запрос имеет высокую точность. Вы можете сделать это с помощью хранимых процедур или встроенного SQL; с чем вам удобнее. Dapper на самом деле вполне подходит для этого варианта использования или просто используйте Enterprise Library с обычными SqlCommand / SqlConnections ..

Дело в том, что не создавайте свой собственный ORM, если вы не понимаете проблему с существующими.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...