.NET ORM нужны виртуальные и не могут работать с запечатанными? - PullRequest
13 голосов
/ 19 марта 2011

Я только начинаю работать с .NET ORM, и до такой степени, что я даже не определился между Entity Framework и NHibernate.Но в обоих случаях я сталкиваюсь с проблемой, заключающейся в том, что они, похоже, хотят, чтобы я нарушил целостность моей предметной модели различными способами, особенно в отношении более тонких аспектов проектирования объектов C #.Это один из нескольких вопросов по этому вопросу.


Существует причина virtual, не используемая по умолчанию для методов в C # .Объекты в моей доменной модели не готовы давать обещания о поведении подклассов, за исключением очень специфических случаев, когда я отмечаю их как таковые.Иными словами, для очень немногих методов в моих объектах домена целесообразно добавить ловушку для неуказанной новой функциональности.

И все же NHibernate хочет, чтобы я сделал все virtual, а Entity Framework хочет, чтобы я сделал все сущностиссылки virtual.Я понимаю, зачем им это нужно (для создания прокси-объектов), и я понимаю, что на самом деле это законное использование наследования, и virtual --- они на самом деле подключаются к моим свойствам, чтобы добавить новую функциональность,Но меня радует, что я должен аннотировать свои классы модели предметной области чем-то, что целиком и полностью связано с постоянством, а вовсе не выражает их фактический контракт с разработчиками и потребителями.

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


Огорчает, что после нескольких лет чтения книг типа Эффективные C # или блоги, подобные тем, что пишут Эрик Липперт, которые дают отличный совет о том, как создавать выразительные и пуленепробиваемые объекты C #, необходимость использовать ORM заставляет меня выбросить большую часть этих знаний из окна.Я надеюсь, что кто-то здесь может указать, где я не прав, либо в моём понимании их возможностей, либо в моих мыслях о моделировании предметной области и роли ORM.

Ответы [ 5 ]

19 голосов
/ 19 марта 2011

Это не просто .NET ORM - те же ограничения применяются и к Java ORM.

Хотя в Java все виртуально, если вы явно не заявите иначе, поэтому необходимость удовлетворения ORM очень похожа на ситуацию, с которой вы сталкиваетесь sealed:

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

Что сводится к следующему: постоянное невежество - стоящая цель, но она не может быть достигнута на 100%, если вы не захотите игнорировать также мелкие детали, такие как загрузка памяти и производительность , а также.

Если загрузка памяти и производительность не имеют значения, прекратите использование прокси-серверов и потребуйте полного заполнения всех ваших объектов, как только они будут увлажнены - NHibernate может сделать это с помощью конфигурации. Побочным эффектом будет то, что все связанные объекты будут загружены за один раз, так что вы получите большую часть базы данных, загруженной в память. Приложению потребуется много памяти и много времени для запуска, но оно будет работать.

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

8 голосов
/ 19 марта 2011

Как это мягко сказать ... Извините, я не могу. Преодолей это.

Я согласен с вами на 100%, но использование фреймворков всегда означает компромисс. Не хотите идти на компромисс? Построй его сам. Это действительно все, что нужно сделать.

Чтобы быть немного менее антагонистичным, есть решение вашей проблемы, и для этого нужно использовать что-то вроде autopper для преобразования между вашей подсистемой с утечкой персистентности и остальной частью вашего приложения. По сути, вы поддерживаете свою модель домена в чистоте и порядке и разрабатываете ее так, как вам нравится, а затем используете слой перевода для сопоставления между ней и вашим отвратительным, уродливым ORM.

Но это действительно много работы. И ради небольшой чистоты, от которой вы отказываетесь, вы экономите много усилий.

6 голосов
/ 19 марта 2011

Виртуальная причина не по умолчанию для методов в C # [ссылка на интервью с Андерсом Хейлсбергом.

Хейлсберг на самом деле говорит о разработке API фреймворка. Он ничего не говорит о приложениях Line of Business. Поэтому его правила применяются меньше в приложениях LOB. Поскольку вы используете O / RM, вы, вероятно, пишете приложение LOB.

часто это выразительно комментировать мой занятия с запечатанным на все обычное причины [ссылка на блог Эрика Липперта].

Вы ссылаетесь на одну из статей Эрика Липперта, который написал эту статью в контексте своей работы в команде компилятора C #. Общие Руководство по проектированию рамок фактически содержат противоположное руководство:

НЕ печать классов без хорошая причина для этого. [пункт 6.3]

Другими словами, то, что говорит Эрик Липперт, это , а не общее правило.

Лично, когда я пишу LOB-приложения, я фактически запечатываю свои классы и пишу не виртуальные методы, когда это возможно. Однако это не имеет ничего общего с внесением критических изменений в более позднюю версию, потому что это почти исключительно проблема проектирования фреймворка.

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

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

Очевидно, что вам также нужна эта гибкость, и поскольку вы пишете LOB-приложение, просто будьте практичны и помните, что:

Все равно они больше похожи на руководящие принципы

1 голос
/ 20 марта 2011

Я понимаю разочарование. Одной из возможностей является использование инфраструктуры аспектно-ориентированного программирования (AOP), такой как PostSharp, для маркировки всех свойств virtual во время компиляции. Недостатком этого является издержки, связанные с процессом ткачества PS, что увеличивает общее время компиляции.

Просто для удовольствия: сейчас я работаю над исследовательским проектом, который представляет собой предварительную ORM на основе AOP (предварительно называется Trinity). Его цель - обеспечить полную емкость для отложенной загрузки без необходимости использования прокси (или ключевого слова virtual). Наиболее важно то, что он позволяет моделям сохранять независимость (не требует наследования, объекты POCO и т. Д.), Но предоставляет те же возможности, что и NHibernate.

АОП все еще находится на уровне исследований, но это был интересный проект для работы. Я постараюсь открыть исходный код проекта, как только статья будет готова.

0 голосов
/ 20 марта 2011

Не обязательно делать все virtual в NHibernate. Если вы не используете «динамические прокси», вам не нужно делать все виртуальным, и вы можете сделать свои классы запечатанными.

NHibernate по умолчанию использует динамические прокси. Таким образом, NHibernate создает класс, который наследуется от вашего класса, чтобы он мог убедиться, что при получении экземпляра заполняется только идентификатор этого класса. Свойства класса будут загружены только тогда, когда вам сначала потребуется доступ к одному из свойств.

Вы можете отключить функцию динамического прокси, указав lazy=false в вашем отображении классов:

<class name="MyEntity" table="SomeTable" lazy="false">
</class>
...