По моему ограниченному опыту, все так, как вы описываете - это беспорядочная ситуация, и применяется обычный ответ «все зависит».
Хорошим примером будет интернет-магазин, в котором я работаю. У него есть объект Brand
, и на главной странице веб-сайта все бренды, которые продает магазин, перечислены на левой стороне. Чтобы отобразить это меню брендов, все, что нужно сайту, это целое число BrandId
и строка BrandName
. Но объект Brand
содержит целый набор других свойств, в частности, свойство Description
, которое может содержать существенно больший объем текста о Brand
. Нет двух способов: загрузить всю эту дополнительную информацию о бренде, просто чтобы выложить его название в неупорядоченном списке, (1) измеримо и значительно медленно, обычно из-за больших текстовых полей и (2) довольно неэффективно, когда оно появляется использования памяти, создания больших строк и даже не глядя на них, прежде чем выбросить их.
Одна опция, предоставляемая многими ORM, - это ленивая загрузка свойства. Таким образом, мы могли бы получить объект Brand
, возвращенный нам, но это трудоемкое и бесполезное для памяти поле Description
недоступно, пока мы не попытаемся вызвать его средство доступа get
. В этот момент прокси-объект перехватит наш вызов и высосет описание из базы данных как раз вовремя. Иногда это достаточно хорошо, но я сжигаю столько раз, что лично не рекомендую:
- Легко забыть, что свойство загружается лениво, создавая проблему SELECT N + 1, просто написав цикл foreach. Кто знает, что происходит, когда LINQ вмешивается.
- Что, если вызов базы данных «точно вовремя» завершится неудачно из-за сбоя транспорта или выхода из сети? Я могу почти гарантировать, что любой код, который делает что-то столь же безобидное, как
string desc = brand.Description
, не ожидал, что этот простой вызов бросит DataAccessException
. Теперь вы только что разбились противным и неожиданным способом. (Да, я видел, как мое приложение упало из-за этого. Изучил трудный путь!)
Итак, что я в итоге сделал, так это то, что в сценариях, требующих производительности или склонных к взаимоблокировке базы данных, я создаю отдельный интерфейс, который веб-сайт или любая другая программа могут вызывать для получения доступа к определенным порциям данных, которые имеют тщательно изучили свои планы запросов. Архитектура выглядит примерно так (простите за искусство ASCII):
Web Site: Controller Classes
|
|---------------------------------+
| |
App Server: IDocumentService IOrderService, IInventoryService, etc
(Arrays, DataSets) (Regular OO objects, like Brand)
| |
| |
| |
Data Layer: (Raw ADO.NET returning arrays, ("Full cream" ORM like NHibernate)
DataSets, simple classes)
Раньше я думал, что это обман, подрывая объектную модель ОО. Но в практическом смысле, пока вы делаете этот ярлык для отображения данных, я думаю, что все в порядке. Обновления / вставки и то, что вы по-прежнему проходите через полностью гидратированную, заполненную ORM модель домена, и это происходит гораздо реже (в большинстве моих случаев), чем отображение определенных подмножеств данных. ORM, такие как NHibernate, позволят вам делать прогнозы, но к этому моменту я просто не вижу смысла ORM. В любом случае это, вероятно, будет хранимая процедура, написание ADO.NET занимает две секунды.
Это всего лишь два моих цента. Я с нетерпением жду, чтобы прочитать некоторые другие ответы.