2010-10-05 4 views
0

У меня есть постоянные проблемы с дизайном модели в MVC. В основном для всех моих проектов требуются некоторые объекты, которые должны быть созданы, отредактированы и удалены. Большинство из этих объектов имеют некоторые общие свойства, такие как дата создания, измененная дата, автор, модифицированные и в некоторых случаях даже более описательные свойства являются общими. Из-за этого у меня есть одна таблица DB для их хранения. Например, таблица «Документы», и мы храним в ней счета-фактуры, котировки и другие деловые документы. Я использую Entity Framework v4 для ORM, где мы, в конечном итоге, получаем объект Document.Дизайн модели в ASP.NET MVC

Как изменить этот объект или создать отдельный класс DocumentViewModel для поддержки нескольких типов документов с общими свойствами (так что должна быть реализована определенная форма наследования или реализация интерфейса)? Помимо идентификации разных типов документов, мне также необходимо иметь некоторые типы, чтобы иметь разные правила аннотации данных (атрибуты).

Например, в таблице документов есть столбец PayDate. Тип документа Счета требует, чтобы PayDate предоставлялся, но тип документа Котировка не используется.

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

+1

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

+0

Это правильный вопрос, Гектор, но я стараюсь балансировать между лучшими практиками и простотой дизайна. Похоже, что два принципа: «Разделение забот» и «СУХИЕ» («Не повторяй себя») часто противоречат самим себе. – mare

+1

Я не уверен, что кто-нибудь здесь может дать вам инструкции о том, как правильно создать свой доменный уровень. Это может сделать только человек с полным пониманием бизнеса. Это ваш первый раз, когда вы делаете дизайн, ориентированный на домен? Вы сделали OO в прошлом?Мой опыт работы с Stackoverflow заключается в том, что группа здесь отлично подходит для ответа на вопросы с жесткой сферой, но не столько для широких потребностей. Я бы посоветовал, если вы впервые разрабатываете доменный уровень, чтобы получить помощь от коллеги или сделать некоторые чтения по этому вопросу. – bzarah

ответ

2

Считаете ли вы, что делать Документы предприятие аннотация?

С стороны БД у вас будет Документы таблица, содержащая только поля, разделяемые всеми счетами-фактами/итомами. В этом поле будет IDENTITY PK - например DocId.

В других таблицах, дополнительные мета-данные, специфичные для данного документа могут быть сохранены, а ПК является (нетождества) поле DocId, который также является ФК к Документы таблицы.

На стороне EF, Документов становится абстрактной сущности и другие объекты наследуют от этого объекта. Это позволяет создать хорошую парадигму ОО и сделать ваш код более надежным.

В настоящее время мы используем эту схему (EF4/SQL Server).

Ваш сценарий звучит очень похоже на наш - рассмотрим использование абстрактных классов.

EDIT

Мысль я хотел бы добавить немного больше информации о том, как я на самом деле реализован этот сценарий, чтобы поставить вас на правильном пути.

Как комментарии к вашему состоянию Q, у нас мало знаний о вашем домене, поэтому сложно сделать обоснованные мнения. Лично я решил сделать свой объект аннотация, потому что для некоторых функций требовалось «смешанная сумка» предметов, которые нужно вернуть за один удар. Конечно, есть другие способы сделать это (например, хранимая процедура), но это позволяет хорошо владеть интерфейсом между моим пользовательским интерфейсом (кстати, MVC) и моим уровнем обслуживания.

как это работает - вот как я получаю одного Сообщение:

// var is strongly-typed to a "Post" 
var somePost = repository.FindSingle(10); 

Вот как я получаю смешанный мешок сообщений:

// var is strongly-typed to a "ICollection<Post>". 
// "Title" is a property on my "Post" abstract POCO 
var mixedBagOfPosts = repository.FindAll<Post>(p => p.Title = "Some Title"); 

Вот как я получаю сборник «Обзоры» (ребенок почты):

// var is strongly-typed to a "ICollection<Review>" 
// "Rating" is a property on my "Review" POCO (derived from Post) 
var reviews = repository.FindAll<Review>(r => r.Rating == 5.00); 

Кикер мое хранилище осуществляется с обобщениями, а параметр типа обеспечивает безопасность типов:

ICollection<T> FindAll<T>(Expression<Func<T,bool>> predicate) where T : Post 

И это реализовано так:

return myContext.Posts.OfType<T>.Where(predicate).ToList(); 

OfType вызывает внутреннее соединение в T (который является дочерней таблицей), поэтому возвращаются только те записи.

Конечно, у меня также есть служебный уровень , посредник между моим пользовательским интерфейсом и репозиторием, но это должно помочь вам на правильном пути.

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

Если вам это не нравится, вы можете, конечно, иметь регулярные параметры (название строки и т. Д.).

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

+0

1. Итак, вы устанавливаете сущность абстрактно в дизайнере EDM, устанавливая Abstract в true? 2. Как вы создаете репозиторий доступа к данным вокруг такого дизайна? Вы работаете напрямую с унаследованными классами/сущностями? – mare

+0

Да - вы устанавливаете «Документы» в абстракцию (окно свойств) и устанавливаете «базу» для остальных «Счета-фактуры», «Котировки» - сущность «Документы». Я использовал шаблон репозитория вокруг него с помощью дженериков. Это много (я имею в виду много), чтобы объяснить, возможно, посмотрите на некоторые из моих вопросов, которые я задал (так как я недавно общался с этим), и заглядываю в google для «EF Abstract Classes». Это можно сделать, хотя мы делаем это сейчас - EF4, SQL 2008, шаблон репозитория, POCO (с абстрактным) и т. Д. – RPM1984

+0

И чтобы ответить на ваши вопросы: 1. Да. И поскольку я использую POCO, мой абстрактный объект также является абстрактным классом. 2. Мои методы хранилища выглядят так: 'ICollection Найти (Expression > предикат), где T: Post'. (Сообщение - мой абстрактный класс). Поэтому я использую дженерики. Это позволяет мне возвращать «смешанную сумку» классов (так что у вас может быть один метод, возвращающий все типы документов). Это позволяет вашему приложению намного больше OO. – RPM1984

0

Много раз вы можете поместить таблицу в свою EF-модель и просто переименовать ее в объекты, которые вам нужны. Просто удалите столбцы, которые вам не нужны.

Например, введите объект документа ... теперь переименуйте его в счет-фактуру. Теперь добавьте еще один, и назовите его Quotation ... в Quotation, нажмите PayDate и нажмите клавишу удаления. Вы можете настроить все, что хотите! Вы можете сделать то же самое с другими ORM, просто потребуется немного больше работы. С NHibernate вы вручную создадите Модели, а затем сопоставляете их с одной и той же таблицей, но только сопоставляете то, что вам нужно.

+0

Как вы можете добавить еще один? Я могу только «Обновить модель из базы данных ..» и добавляет один экземпляр каждой таблицы в качестве объекта и устанавливает ассоциации. Если я хочу его дважды, мне нужно скопировать его, а затем переименовать. Затем я могу делать то, что вы говорите, но у этого объекта не было бы никаких ассоциаций, поэтому я должен был бы установить их вручную, что довольно сложно с множеством связанных объектов. Пожалуйста, объясните – mare

+0

Хорошо, я думал, что EF сделал это легко, но я ошибаюсь ... Я думал о Linq для SQL, я думаю. В EF вам нужно будет открыть XML и отредактировать, чтобы сделать эту работу. Я знаю, что это не то, что вы хотите услышать, но эй, этот материал не прост, и для того, чтобы сделать все, что нужно для вашего ORM-сопоставления, будет стоить MS слишком много денег. Вот почему EF был настолько медленным, чтобы добраться до этого момента. – CrazyDart

+0

Что вы говорите, EF широко признан как более зрелый ORM, чем L2SQL, а графический интерфейс - тот же, что и L2SQL (лучше на самом деле). Отображение выполняется в GUI - мне никогда не приходилось касаться файла XML (кроме того, когда я делал некоторые сложные вещи POCO). – RPM1984

Смежные вопросы