tag:blogger.com,1999:blog-458002489272917533.post9206175735814392187..comments2024-02-14T14:07:38.890+05:00Comments on Блог Александра Бындю: ViewModel и Domain Model: Границы ответственностиAlexander Byndyuhttp://www.blogger.com/profile/14185486842573956085noreply@blogger.comBlogger33125tag:blogger.com,1999:blog-458002489272917533.post-33217305727222052372012-06-19T10:42:30.006+06:002012-06-19T10:42:30.006+06:00Я понимаю проблемы, с которыми вы столкнулись. Сам...Я понимаю проблемы, с которыми вы столкнулись. Сам когда-то генерировал объекты по БД <br />http://blog.byndyu.ru/2009/12/llblgen-vs-nhibernate.html<br /><br />Первое, что лучше всего сделать, перейти на Code First.<br /><br />Если проект очень большой, давно разрабатывается и так просто от генерации не отказаться, то есть несколько вариантов.<br /><br />1. Использовать то, что уже есть. Alexander Byndyunoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-38986661935107703992012-06-07T13:15:56.385+06:002012-06-07T13:15:56.385+06:00Здравствуйте. По этой теме возник такой вопрос:
Им...Здравствуйте. По этой теме возник такой вопрос:<br />Имеется 3 уровня(представление, БД, и БЛ).<br />В качестве доступа к БД используем EntityFramework. Но объекты, которые он генерирует мне не нравится, к тому же для их использования надо везде носить с собой всю модель(то есть доступ к БД получается).<br />Правильно создать еще объекты, аналогичные сгенерированным(но более упрощенные и Sky Dragonnoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-74206246532643851312012-05-30T21:11:09.761+06:002012-05-30T21:11:09.761+06:00Когда идёт прорисовка данных из враппера на форме,...Когда идёт прорисовка данных из враппера на форме, то проблем никаких не вижу. во 2й операции - сбор данных с формы во враппер конечно просто так вложенные объекты не наполнятся. Значит надо подключать всю мощь ООП и своего мозгового аппарата.Alexnoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-86924087960532447652012-05-30T20:34:35.622+06:002012-05-30T20:34:35.622+06:00Вопрос в том, что делать если у вас идет обращение...Вопрос в том, что делать если у вас идет обращение к вложенным полям сущностей, например, вот такт Post.Comments[1].Author.Namealexanderbyndyunoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-28647773830785750332012-05-30T20:32:20.195+06:002012-05-30T20:32:20.195+06:00 1. На веб форме описываю враппер как модель
@mode... 1. На веб форме описываю враппер как модель<br />@model Web.Model.Wrappers.JournalEntryWrapper<br /><br />2. Для рисования данных из враппера на форме<br />return View(new JournalEntryWrapper(id));<br /><br />3. Для сбора данных с формы во враппер<br /> [HttpPost]<br /> public ActionResult Create(int id, JournalEntryWrapper entry)<br /> { .... }<br /> то есть никакой Alexnoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-3513506272827746492012-05-30T19:59:04.970+06:002012-05-30T19:59:04.970+06:00Спасибо, идея понятна.
Что вы делаете, когда надо ...Спасибо, идея понятна.<br />Что вы делаете, когда надо выводить и забирать вложенные объекты/коллекции? Может ли при этом появляться дублирование в коде, которые "маппит" вложенные объекты/коллекции?alexanderbyndyunoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-46097763549894664102012-05-30T19:42:44.009+06:002012-05-30T19:42:44.009+06:00 journal_entry - это сущность Domain Model:
Journa... journal_entry - это сущность Domain Model:<br />JournalEntryWrapper - это сущность ViewModel<br /><br /> public class JournalEntryWrapper <br /> {<br /> public journal_entry JournalEntry { get; set; }<br /><br /> public JournalEntryWrapper()<br /> {<br /> JournalEntry = new journal_entry();<br /> }<br /><br /> public JournalEntryWrapper(int Alexnoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-63211823857791153202012-05-30T16:58:54.493+06:002012-05-30T16:58:54.493+06:00Запрос вернет DTO, который будет отображаться на V...Запрос вернет DTO, который будет отображаться на View. Назовите его не DTO, а ViewModel, суть такая же:<br /><br />return new View(new ComplexViewModel{Tags = tagsViewModel,Posts = postsViewModel,....}); alexanderbyndyunoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-27864680801276852272012-05-30T16:57:13.090+06:002012-05-30T16:57:13.090+06:00В первом варианте разве не будет жесткого связыван...В первом варианте разве не будет жесткого связывания между ViewModel и тем типом, который возвращает запрос? <br />У меня сейчас как раз второй вариант, с небольшими собственными допиламиgleb Chermennovnoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-58813370466734739282012-05-30T14:52:23.536+06:002012-05-30T14:52:23.536+06:00Возможно для какого-то суперсложного объекта и нуж...Возможно для какого-то суперсложного объекта и нужен AutoMapper. Но у меня все объекты прекрасно мапятся и без него, исключительно встроенными средствами asp.net mvcAlexnoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-70678585071830810382012-05-30T13:46:39.535+06:002012-05-30T13:46:39.535+06:00Первый вариант из запроса возвращать DTO и складыв...Первый вариант из запроса возвращать DTO и складывать их во ViewModel.<br /><br />return new View(new ComplexViewModel{<br />Tags = tagsDto,<br />Posts = postsDto,<br />....<br />});<br />Второй вариант делать ViewModel вручную, вызывая Automapper.<br />return new View(new ComplexViewModel{Tags = Automapper.Mat<>(tags),....});alexanderbyndyunoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-49665962061272687292012-05-30T13:40:00.097+06:002012-05-30T13:40:00.097+06:00dfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfggleb Chermennovnoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-78687860689087041252012-05-30T08:28:22.597+06:002012-05-30T08:28:22.597+06:00Глеб, я не совсем понимаю из-за чего распухает кон...Глеб, я не совсем понимаю из-за чего распухает контроллер. В вашем случае в нем будет:<br /><br />// вызов Query<br /><br />// составление Model (хотя Query может возвращать сразу готовые DTO и эта часть будет отсутствовать)<br /><br />// return View(model)alexanderbyndyunoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-27272707632298788382012-05-30T00:14:52.835+06:002012-05-30T00:14:52.835+06:00Спасибо за статью, Александр. Давно задаюсь вопрос...Спасибо за статью, Александр. Давно задаюсь вопросом - что делать, если во View нужно показать много данных из разных таблиц БД (причем не только выборки, но и аггрегация в том числе)? Мне далеко до эксперта в MVC, но как правило в этой ситуации у меня получается сложный класс ViewModel и несколько запросов к БД. В этот ViewModel через AutoMapper отображаются результаты запросов. Маппинг Gleb Chermennovhttp://twitter.com/chester89noreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-20454112017021564842012-05-29T23:13:05.716+06:002012-05-29T23:13:05.716+06:00Алекс, покажите код, про который вы рассказываете....Алекс, покажите код, про который вы рассказываете. Хочу увидеть, как это у вас реализовано.<br /><br />> В этом флейме обсуждается использование AutoMapper. Не вполне понимаю зачем он<br /><br />Он нужен, чтобы из доменного объекта сделать ViewModel и обратно. Binder от MVC такого сделать сам не сможет, особенно, когда ViewModel сложная, а не просто набор примитивных типов. alexanderbyndyunoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-47411807870140875772012-05-29T21:53:54.733+06:002012-05-29T21:53:54.733+06:00Александр, спасибо за статью!
Крайне приятно увид...Александр, спасибо за статью! <br />Крайне приятно увидеть что подобные вопросы интересуют наше сообщество. По своему опыту могу сказать что именно asp.net mvc дала возможность заглянуть в такие вопросы. В обычном asp.net у меня таких вопросов не было - всё было крайне прозаично. <br /><br />Теперь по теме - моё субъективное мнение по опыту работы с asp.net mvc. Безусловно ViewModel и Domain Alexnoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-77131747937630980712012-05-10T01:09:20.999+06:002012-05-10T01:09:20.999+06:00Нет, я не к тому, что вариант 1 был рассмотрен нед...Нет, я не к тому, что вариант 1 был рассмотрен недостаточно и был "нечестно загнана в угол". Все замечательно. Прост тон статьи такой, что ее следовало бы назвать: "Почему использовать ViewModel почти всегда лучше" (ну, или как-то в этом роде).<br /><br /><br />На самом деле в нашей команде применялся как раз подобный подход. В качестве ORM мы использовали NHibernate, а там, ArtemGlazkovnoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-32360506778456401522012-05-10T00:26:16.168+06:002012-05-10T00:26:16.168+06:00Артем, я честно рассмотрел каждый вариант в каждом...Артем, я честно рассмотрел каждый вариант в каждом сценарии :)<br /><br />Вывод я сделал исходя из рассмотренного и моего опыта разработки. Думаю, что он вполне закономерен.Alexander Byndyunoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-19530408092491134012012-05-10T00:21:40.888+06:002012-05-10T00:21:40.888+06:00Спасибо за статью. Статья замечательная.
Правда, н...Спасибо за статью. Статья замечательная.<br />Правда, на мой взгляд, есть одна небольшая нестыковка - чисто текстуальная. В самом начале Вы говорите про то, что рассмотрите "... оба варианта в разных сценариях использования системы" и сделаете "в конце ... выводы по выбору одного или другого решения". По факту же вся статья сводится к доказательству почти безусловного ArtemGlazkovnoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-8855229454194615502012-05-07T14:14:55.000+06:002012-05-07T14:14:55.000+06:00как минус передачи на view Domain Entities - это т...как минус передачи на view Domain Entities - это то что постоянно приходится заботиться о model binding security и сигнатуры action начинают обрастать : FooAction(Bind(Include="ID,Email,Website,Body")]FooDomainEntity entity)Eugene Sergueevnoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-59742148105603935072012-05-07T00:26:51.387+06:002012-05-07T00:26:51.387+06:00Ясно, направление есть - займусь изучением вопроса...Ясно, направление есть - займусь изучением вопроса поглубже.<br /><br /><br />спасибо!Herman Starzhynskihttp://twitter.com/nikaburunoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-48122036971195441572012-05-07T00:18:36.481+06:002012-05-07T00:18:36.481+06:00Я думаю, что Repository вообще не должно быть
htt...Я думаю, что Repository вообще не должно быть <br />http://blog.byndyu.ru/2011/08/repository.html, вот тут описана замена на бестелесный IQueryFactory <br />http://blog.byndyu.ru/2011/08/queryfactory-iqueryfactory.html<br /><br />Команда принимает на вход форму, если это пост-запрос с формы, либо данные для команды, если это какое-то другое изменение системы. Например, при добавлении статьи методAlexander Byndyunoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-51503706913599321112012-05-07T00:13:43.347+06:002012-05-07T00:13:43.347+06:00как я понимаю, Вы говоритье про CQRS принцип. Полу...как я понимаю, Вы говоритье про CQRS принцип. Получается у нас репозитории не должны лежать на уровне ниже сервисов, а должны быть на одном уровне и контроллер использует либо репозитории (для гет запросов в общем), либо сервисы (для пост запросов). И в этом случае, если сервису нужны доп. данные, то сервис обращается тоже к репозиторию.<br /><br />Или всё таки у нас есть низкоуровневые Herman Starzhynskihttp://twitter.com/nikaburunoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-5617000433276837122012-05-06T23:53:21.887+06:002012-05-06T23:53:21.887+06:00Да, так получается в "общем" случае, но ...Да, так получается в "общем" случае, но не получается в реальной жизни.<br /><br />Разбейте сервисы и репозитории на небольшие классы. Сервисы на команды, репозитории на Query. Тогда у вас будет Controller -> Query (map to DTO) -> Controller -> ViewAlexander Byndyunoreply@blogger.comtag:blogger.com,1999:blog-458002489272917533.post-51206552036164692092012-05-06T23:48:35.516+06:002012-05-06T23:48:35.516+06:00Класная статься, спасиб!
Интересен ещё один момен...Класная статься, спасиб! <br />Интересен ещё один момент. Дано: класы данных из базы (доменные объекты у нас), репозитории для их извлечения, сервисы бизнес логики и сверху MVC. Простейший сценарий: получить, например, пользователя. Он лежит в базе в таблице пользователи и с помощью орм от туда получается. <br />Пример для понимания всего процесса и понятно, что может и через урощённую схему Herman Starzhynskihttp://twitter.com/nikaburunoreply@blogger.com