Entity Framework, уровни приложений и разделение проблем

Я использую Entity Framework 4.1 и ASP.Net MVC 3 для своего приложения. MVC предоставляет уровень представления, промежуточная библиотека предоставляет бизнес-логику, а Entity Framework как бы действует как уровень данных, я полагаю?

Я мог бы разделить код Entity Framework на набор классов репозитория или его соответствующий вариант, что бы ни составляло полезный уровень данных, но у меня возникают проблемы с решением возникшей у меня проблемы дизайна.

Если существует многоуровневый подход, который помогает мне разделять проблемы, тогда очевидно, что мой выбор сохранения данных также не должен быть проблемой для уровня представления. Проблема в том, что, используя Entity Framework, я в основном жестко привязываю свое приложение к понятию, что изменения сущностей отслеживаются и сохраняются автоматически.

Таким образом, скажем, в гипотетическом мире я нашел причину не использовать Entity Framework и хотел заменить ее. Хорошо спроектированное решение должно позволить мне делать это на соответствующем уровне и не затрагивать зависимые уровни, но поскольку весь код пишется с учетом того, что уровень данных отслеживает изменения объекта, я мог бы только заменить Entity Фреймворк для чего-то, что работает аналогичным образом, например nHibernate.

Как мне использовать Entity Framework, но не нужно писать код таким образом, чтобы предполагать, что изменения сущности отслеживаются уровнем данных?

ОБНОВЛЕНИЕ для тех, кто все еще задается вопросом об этой проблеме в своих собственных сценариях:
Айенде Рахиен написала отличную статью, опровергающую весь этот аргумент: http://ayende.com/blog/4567/ложный-миф-об-инкапсуляции-доступа-данных-в-далеке


person Nathan Ridley    schedule 11.05.2011    source источник


Ответы (4)


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

В Agile-методологиях есть действительно интересное явление: не готовьтесь к гипотетическим ситуациям. В большинстве случаев это просто позолота. Каждое изменение имеет свою стоимость. Изменение уровня сохраняемости на более поздних этапах проекта требует больших затрат, но также встречается очень редко. С точки зрения заказчика, нет причин оплачивать часть этих затрат в большинстве проектов, где это изменение не требуется. Если мы обсудим точку зрения клиента более глубоко, мы можем сказать, что он вообще не должен платить за это, потому что выбор плохого API, который необходимо заменить позже, является неудачей разработчиков / архитекторов. Регулярно реорганизуйте код, но только до той степени, которая необходима для добавления новых функций, которые нужны заказчику, в противном случае вы вряд ли сможете быть конкурентоспособными на рынке. Конечно, есть исключения:

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

Теперь к твоей проблеме. Если вам нужна такая абстракция высокого уровня, вы не должны открывать сущности своему контроллеру. Раскройте DTO из бизнес-уровня (или даже из репозиториев) и добавьте в эти DTO поля, такие как IsNew, IsModified, IsDeleted. Теперь ваш пользовательский интерфейс полностью отделен от персистентности, но ваша архитектура намного сложнее, и, вероятно, нет причин для такой сложности - она ​​чрезмерно спроектирована. Другой способ - просто отключить отслеживание (добавить AsNoTracking() к каждому запросу) и создать прокси для ваших сущностей (context.Configuration.ProxyCreationEnabled) - ленивая загрузка также не будет работать. Это все равно что отбросить большинство функций, которые вам предлагают фреймворки с сохраняемостью.

Есть и другие точки зрения. Я рекомендую вам прочитать последние сообщения Айенде о репозитории и его комментарии к архитектуре Sharp.

person Ladislav Mrnka    schedule 11.05.2011
comment
Просто хотел добавить, что все ORM также имеют множество различий, которые было бы трудно заменить. В первую очередь отличия включают поведение каскадного удаления, поведение нетерпеливой загрузки, поведение linq (например, необходимо выполнить порядок, прежде чем пропустить прием с помощью ef), сохраненное поведение proc / view, поведение ad-hoc sql, поведение проекции даже с linq. Мифического заменяемого слоя ORM не существует. В любом случае вам предстоит много работать. - person John Farrell; 12.05.2011
comment
Отличный ответ! Честно говоря, иногда мне просто нужно оттолкнуть это от других, чтобы успокоить свой разум. - person Nathan Ridley; 12.05.2011
comment
Это хорошая точка зрения для одного приложения, но что, если вы планируете написать несколько приложений, и все они должны использовать одни и те же базовые концепции (и, возможно, код - также известный как библиотека). Тогда все усложняется, и вы не можете просто создать то, что хочет заказчик (он все равно не знает). - person Marc; 06.07.2017

Короткий ответ? Вы этого не сделаете. Вы можете отключить отслеживание EF и не беспокоиться об этом, но это все.

Если вы собираетесь писать свой уровень презентации с ожиданием, что изменения будут отслеживаться и сохраняться автоматически, то все, что вы заменяете EF, должно делать это. Вы не можете поменять его на что-то, что не отслеживает и не сохраняет изменения автоматически, и просто ожидайте, что все будет работать. Это все равно что взять систему, которая использует TCP / IP-соединение для дуплексной связи, заменить ее на HTTP-соединение (которое по своей природе не является дуплексным) и ожидать, что все будет работать так же. Это не так.

Если вы хотите иметь возможность поменять свой уровень сохраняемости на что-то еще и не менять что-либо еще, вам нужно обернуть EF (или что-то еще) в свой собственный код, чтобы обеспечить желаемую функциональность. Затем вы должны предоставить реализации для всего, что не предусмотрено тем, на что вы переключаетесь.

Это выполнимо, но это будет ужасно много работы для решения проблемы, которая на самом деле случается очень редко. Это также добавит сложности проекту. Ладислав не унывает: не стоит так далеко абстрагироваться.

person Tridus    schedule 11.05.2011

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

На Codeplex есть отличный проект, который охватывает дизайн, управляемый доменом, включая документацию. Взгляни на это.

http://microsoftnlayerapp.codeplex.com/

person William Xifaras    schedule 11.05.2011
comment
Мне кажется, что это побеждает цель настойчивого невежества. Уровень моего контроллера не должен заботиться о том, использую ли я модель ORM или репозиторий. - person Nathan Ridley; 11.05.2011
comment
Если эти две вещи не обеспечивают одинаковой функциональности, то вам определенно следует позаботиться о вашем уровне контроллера. То, что автоматически отслеживает и сохраняет изменения, требует принципиально иной логики контроллера, чем то, что этого не делает. - person Tridus; 12.05.2011
comment
Вы правы, и, как я уже сказал, вы можете использовать простые POCOS и передавать их как DTO - они должны быть постоянными игнорирующими. Шаблон репозитория не заставляет вас использовать какую-либо конкретную методологию доступа к данным. - person William Xifaras; 13.05.2011

После прочтения проекта Microsoft n-layer прочтите блог ayenede. Г-н Айенде опубликовал серию сообщений о преимуществах и недостатках Microsoft n -слойный проект.

person Arash Karami    schedule 28.08.2011