У меня есть веб-решение (в VS2010) с двумя подпроектами:
-
Domain
, который содержит классыModel
(сопоставленные с таблицами базы данных через Entity Framework) иServices
, которые (помимо других вещей) несут ответственность за операции CRUD -
WebUI
, который ссылается на проект домена
Для первых страниц, которые я создал, я использовал классы Model из проекта Domain непосредственно как Model в своих сильно типизированных представлениях, потому что классы были небольшими, и я хотел отображать и изменять все свойства.
Теперь у меня есть страница, которая должна работать только с небольшой частью всех свойств соответствующей модели домена. Я извлекаю эти свойства, используя проекцию результата запроса в моем классе Service. Но мне нужно проект в тип - и вот мои вопросы о решениях, о которых я могу думать:
-
Я представляю
ViewModels
, которые живут в проектеWebUI
и выставляютIQueryables
иEF data context
из службы в проект WebUI. Тогда я мог бы напрямую проецировать на эти ViewModels. -
Если я не хочу раскрывать IQueryables и контекст данных EF, я помещаю классы
ViewModel
в проектDomain
, тогда я могу вернуть ViewModels напрямую в результате запросов и прогнозов из Сервисные классы. -
В дополнение к
ViewModels
в проектеWebUI
я представляюData transfer objects
, который перемещает данные из запросов в классах службы вViewModels
.
Решение 1 и 2 похоже на то же количество работы, и я склонен предпочитать решение 2, чтобы сохранить все проблемы с базой данных в отдельном проекте. Но почему-то кажется неправильным, что в проекте Domain есть модели View-Models.
Решение 3 звучит намного больше, поскольку у меня есть больше классов для создания и ухода за отображением Model-DTO-ViewModel. Я также не понимаю, какая разница между DTO и ViewModels. Не являются ли ViewModels именно коллекцией выбранных свойств моего класса Model, которые я хочу отобразить? Разве они не будут содержать те же члены, что и DTO? Почему я хочу различать ViewModels и DTO?
Какое из этих трех вариантов предпочтительнее и каковы преимущества и недостатки? Существуют ли другие варианты?
Благодарим вас за отзыв!
Изменить (потому что у меня была, возможно, слишком длинная стена текста и была запрошена код)
Пример: у меня есть Customer
Entity...
public class Customer
{
public int ID { get; set; }
public string Name { get; set; }
public City { get; set; }
// ... and many more properties
}
... и хотите создать представление, которое отображает (и, возможно, позволяет редактировать) Name
клиентов в списке. В классе Service я извлекаю данные, которые мне нужны для представления через проекцию:
public class CustomerService
{
public List<SomeClass1> GetCustomerNameList()
{
using (var dbContext = new MyDbContext())
{
return dbContext.Customers
.Select(c => new SomeClass1
{
ID = c.ID,
Name = c.Name
})
.ToList();
}
}
}
Тогда есть CustomerController с методом действия. Как это должно выглядеть?
Либо этот способ (а)...
public ActionResult Index()
{
List<SomeClass1> list = _service.GetCustomerNameList();
return View(list);
}
... или лучше (b):
public ActionResult Index()
{
List<SomeClass1> list = _service.GetCustomerNameList();
List<SomeClass2> newList = CreateNewList(list);
return View(newList);
}
Что касается варианта 3 выше, я бы сказал: SomeClass1
(живет в проекте Domain
) - это DTO и SomeClass2
(живет в проекте WebUI
) - это ViewModel.
Мне интересно, имеет ли смысл различать два класса. Почему бы мне не выбрать вариант (а) для действия контроллера (потому что это проще)? Есть ли причины ввести ViewModel (SomeClass2
) в дополнение к DTO (SomeClass1
)?