Работа с Breeze + ViewModels

В моем приложении у меня есть свой доменный слой и веб-интерфейс (о других слоях я не буду вдаваться в подробности).

Мои представления, работа с объектами ViewModels и база данных сохраняют объекты домена.
Чтобы преобразовать объект ViewModel в объект домена, я использую AutoMapper.

Проблема с работающим Breeze заключается в том, что когда я создам новый объект var newCust = manager.createEntity('Customer', {name:'Beta'}), это объект домена, и он должен быть объектом ViewModel.

Не все, но в некоторых случаях ViewModel не похожа на предметную область. Например, коллекции объектов в домене: ICollection<Person>, а в модели представления: ICollection<int> int — это ПК человека.

Вопрос

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


person ridermansb    schedule 08.07.2013    source источник
comment
ViewModels и объекты предметной области — это не одно и то же. ViewModels могут и часто раскрывают объекты предметной области. Вы можете использовать фреймворк наподобие durandal.js для обработки композиции view-viewmodel (и многого другого).   -  person pawel    schedule 09.07.2013
comment
Так? Я и не говорил, что они одинаковые! Вопрос в том, как работать с Breeze и ViewModels. В метаданных Breeze определяются только объекты домена. Мне нужно создать объекты ViewModel!   -  person ridermansb    schedule 09.07.2013


Ответы (1)


@ridermansb - Поскольку вы упомянули AutoMapper, я предполагаю, что ваше сопоставление происходит на сервере. Вы хотите, чтобы ваш серверный API открывал «ViewModels» (в этом случае вы могли бы называть их DTO), а не объекты модели предметной области. Иногда ваши ViewModels точно отражают объекты вашего домена; иногда нет.

Ваш клиент видит только то, что предоставляет ваш API. Если это клиент BreezeJS, вы, скорее всего, будете рассматривать ViewModels как объекты на стороне клиента. Они являются сущностями Breeze в том смысле, что вы ожидаете, что Breeze будет запрашивать, кэшировать, отслеживать изменения и проверять их. BreezeJS не знает, соответствуют ли эти «сущности» DTO на стороне сервера или бизнес-объектам на стороне сервера.

Конечно, если вы используете DTO/ViewModels, код вашего сервера отвечает за перевод между формой DTO и формой объекта домена. Предположительно, эта логика лежит где-то между уровнем API на стороне сервера и уровнем домена.

Если вы выбрали эту архитектуру, вы решили иметь дело с двунаправленной трансляцией между ViewModels и объектами предметной области и приняли все связанные с этим сложности и хлопоты. У меня нет слов совета для вас на этот счет.

Итак, позвольте мне перефразировать и сузить ваш вопрос: «Как я могу получить метаданные, описывающие объектную модель, предоставляемую моим серверным API?»

Мой любимый способ (при условии, что сервер .NET) — позволить EF сделать это за меня. Я создаю DbContext, который ссылается НЕ на мои классы модели предметной области, а скорее на мои классы ViewModel/DTO. Конечно, эти классы на самом деле не будут отображаться в реальной базе данных. Без проблем; они не должны. Вы никогда не будете использовать этот DbContext для доступа к данным. Вы будете использовать его только для создания метаданных. Вы используете EF в качестве инструмента для создания метаданных во время разработки... и все. Это эффективный ремонтопригодный подход.

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

Кроме того, вы можете написать метаданные вручную, как описано здесь.

person Ward    schedule 09.07.2013
comment
Я не знаю, как этот подход впишется в мою архитектуру. О классах на самом деле не будет сопоставляться с реальной базой данных, это может вызвать различные проблемы, не знаю, согласны ли с этим, нарушит некоторые функции EF, такие как миграции. - person ridermansb; 11.07.2013
comment
Почему это должно произойти? Какие миграции? Вы используете миграции с базой данных. Нет базы данных, связанной с этим MetadataDbContext. Это просто средство для описания модели объекта, которую EF+Breeze.NET может превратить в метаданные. Здесь нет никакой архитектуры. Опять же... мы говорим о отображении ваших DTO... их отображении в никуда. - person Ward; 11.07.2013
comment
Scaffold использует DbSet ‹T› для создания миграций EF, или я ошибаюсь? Как вы сказали, не всегда DTO являются копиями объектов домена. Кажется неправильным использовать DbContext с DTO. (Я использую EF6 CodeFirst). На мой взгляд, использование DbContext с DTO для легкого создания метаданных этих сущностей кажется неправильным. - person ridermansb; 11.07.2013
comment
Еще одна деталь заключается в том, что DbContext находится на уровне репозитория, а DTOs/ViewModels — это уровень интерфейса, который предотвращает этот подход. - person ridermansb; 11.07.2013
comment
Я думаю, вы путаете производство с инструментами времени проектирования. ПРОБЛЕМ АРХИТЕКТУРЫ НЕТ. Практических препятствий нет. В любом случае вы уже используете EF, поэтому вы не можете сказать, что ненавидите EF. Игнорируйте строительные леса. Игнорировать миграции. Сгенерируйте строку метаданных, экспортируйте ее в файл (из этого получится хороший файл javascript JSON, например, metadata.js) и загрузите ее на веб-страницу оболочки SPA. Перестаньте беспокоиться о чистоте, и вы будете лучше спать. :-) - person Ward; 11.07.2013
comment
Хорошо :) большое спасибо .. т.е. решение. Хотя это нужно делать каждый раз, когда я создаю новую ViewModel/D, это сложно, но это решение. Мы проводили тест с ветерком для развертывания с нашим веб-приложением, чтобы повысить производительность и добавить дополнительную простоту. Но это стало довольно дорого, и тот факт, что он не поддерживает отношения многих ко многим, мешает, а не решил на время отказаться от бриза, несмотря на то, что он считается отличным инструментом. - person ridermansb; 12.07.2013
comment
Спасибо за попытку. Возвращайся скорее :-) - person Ward; 12.07.2013
comment
Уорд, у вас была возможность создать пример с использованием этой техники? Как бы вы использовали SaveChanges в BreezeController, используя технику, описанную выше? Если у меня есть настраиваемые DTO, нужно ли мне создавать SaveDtoName для каждого DTO, который был создан, вместо одного SaveChanges, который сохраняется непосредственно в базу данных при непосредственном использовании DbContext базы данных? - person eesh; 05.08.2013
comment
Итак, я добился некоторого прогресса в этом, и я поделюсь в этом комментарии на случай, если кто-то попытается реализовать предложение, данное в этом ответе. Сначала вам нужно будет создать DBContext, который не поддерживается таблицами базы данных. См. debugrelease.com/2010/11/10/ для получения инструкций о том, как это сделать. Я использую EF 5.0, но инструкции почти такие же. Создание объектов для вашего EDM кажется проще в 5.0, когда вы его создали. Продолжение в следующем комментарии... - person eesh; 05.08.2013
comment
Следующее, что вы заметите, это то, что для вызова _contextProvider.Metadata() (в BreezeController Metadata() Get Web Service) требуется запись в файле web.config для работы без фактического подключения к базе данных. У меня сработало следующее (соответственно отрегулируйте имя вашего EDM). ‹добавить name=VisageViewModelContainer connectionString=metadata=res://*/VisageViewModel.csdl|res://*/VisageViewModel.ssdl|res://*/VisageViewModel.msl; поставщик = System.Data.SqlClient; строка подключения провайдера = 'Источник данных =.;' providerName=System.Data.EntityClient /› - person eesh; 05.08.2013
comment
См. также документацию Breeze по этой теме: Entity Framework как инструмент разработки метаданных . - person Edward Brey; 21.07.2014