powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / Модели
20 сообщений из 20, страница 1 из 1
Модели
    #38216188
evgen12345
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый всем день. Изучаю ASP.NET MVC.
С основами разобрался, теперь меня мучает вопрос как правильно архитектурно разделять между различными слоями модель данных?

Для примера имеем следующую схему:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
public class Customer
{
        public int Id { get; set; }
        public string ShortName { get; set; }
        public string Name1 { get; set; }
        public string Name2 { get; set; }
        public string Name3 { get; set; }
        public ICollection<Document> Documents { get; set; }

        /// <summary>
        /// 1 - Legal
        /// 2 - Person
        /// 3 - Individual
        /// </summary>
        public int CustomerType { get; set; }
}

public class Document
{
        public int Id { get; set; }
        public Customer Customer { get; set; }
        public String Number { get; set; }
        public String Serial { get; set; }

        // 1 - паспорт
        public int DocumentType { get; set; }
        public DateTime DateStart { get; set; }
}

 public class CustomerDb : DbContext
 {
        public DbSet<Customer> Customers { get; set; }
        public DbSet<Document> Documents { get; set; }
}



стоит задача отобразить клиента с паспортными данными.


Я так понимаю нужно написать модель которая будет представлять собой следующее:

Вариант1:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
    public class CustomerModel
    {
        private Customer _customer;
        private Document _passport;

        public int Id
        {
            get { return _customer.Id; }
            set { _customer.Id = value; }
        }

        public string ShortName 
        {
            get { return _customer.ShortName; }
            set { _customer.ShortName = value; }
        }

        public string Name1 
        {
            get { return _customer.Name1; }
            set { _customer.Name1 = value; }
        }
        public string Name2 
        {
            get { return _customer.Name2; }
            set { _customer.Name2 = value; }
        }

        public string Name3 
        {
            get { return _customer.Name3; }
            set { _customer.Name3 = value; }
        }

        public int DocumentId 
        {
            get { return _passport.Id; }
            set { _passport.Id = value; }
        }

        public String Number 
        {
            get { return _passport.Number; }
            set { _passport.Number = value; }
        }

        public String Serial
        {
            get { return _passport.Serial; }
            set { _passport.Serial = value; }
        }

        public DateTime DateStart 
        {
            get { return _passport.DateStart; }
            set { _passport.DateStart = value; }
        }
    }



Вариант 2
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
public class CustomerModel
{
        public int Id{ get; set; }

        public string ShortName { get; set; }
        public string Name1 { get; set; }
        public string Name2 { get; set; }
        public string Name3 { get; set; }

        public int DocumentId { get; set; }
        public String Number { get; set; }
        public String Serial{ get; set; }

        public DateTime DateStart { get; set; }
}



Вариант три:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
// дописываем сущность customer следующим образом
public class Customer
{
        public int Id { get; set; }
        public string ShortName { get; set; }
        public string Name1 { get; set; }
        public string Name2 { get; set; }
        public string Name3 { get; set; }
        public ICollection<Document> Documents { get; set; }

        /// <summary>
        /// 1 - Legal
        /// 2 - Person
        /// 3 - Individual
        /// </summary>
        public int CustomerType { get; set; }

        public Document Passport
        {
             get { return (Documents != null) ? Documents.Where(d => d.DocumentType == 1).FirstOrDefault() : null; }
        }
}

// и в контроллере 
var customer = db.Customers.Include(c => c.Documents).First(_id);




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

Так же интересует вопрос получения этих моделей:
в контроллере ?

написанием какого либо класса доступа к данным который одним методом вернет такую модель?

или вообще вынести все в другую сборку и оперировать какими нибудь соглашениями (интерфейсами) или еще чем?

Вопрос наследования сущностей - класс customer имеет поле тип, в дальнейшем предполагается наследовать от него три класса Person, Legal и Individual, к каждому классу добавится набор уникальных полей, а например для класса Legal будет задача отобразить клиента но вместо паспорта (его у него нет) показать данные ОГРН. Как в таком случае будет выглядеть слой достапу к данным?

Спасибо.
...
Рейтинг: 0 / 0
Модели
    #38216210
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
evgen12345,

если тебе нужно просто отобразить, можешь напрямую передавать во вью Customer и Document объекты.

для целей создания и редактирования объектов тебе может понадобится CustomerModel и DocumentModel.
в таком случае Вариант 2.
и для маппинга тебе поможет Automapper:

var model = Mapper.Map(customer, new CustomerModel());

и наоборот

var customer = Mapper.Map(model, new Customer());
...
Рейтинг: 0 / 0
Модели
    #38216228
evgen12345
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
hVosttevgen12345,

если тебе нужно просто отобразить, можешь напрямую передавать во вью Customer и Document объекты.

для целей создания и редактирования объектов тебе может понадобится CustomerModel и DocumentModel.
в таком случае Вариант 2.
и для маппинга тебе поможет Automapper:

var model = Mapper.Map(customer, new CustomerModel());

и наоборот

var customer = Mapper.Map(model, new Customer());

спасибо за оперативный ответ.

Mapper я так понимаю писать нужно самому?

А что с вопросами наследования и где должна находится логика получения данных - так как это только пример, в реальных более сложных ситуациях просто получать в контроллере сущьности не есть гут?

Так же мне нравиться вариант 3 - он вообще живой?
...
Рейтинг: 0 / 0
Модели
    #38216234
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
evgen12345,

нет, маппер писать самому не надо.

где-то при запуске приложения надо выполнить следующее:

Mapper.CreateMap<Customer, CustomerModel>();
Mapper.CreateMap<CustomerModel, Customer>();

Mapper.CreateMap<Document, DocumentModel>();
Mapper.CreateMap<DocumentModel, Documetn>();

если нужны какие-то преобразования в логике маппинга, они здесь же конструируются, например:

Mapper.CreateMap<CustomerModel, Customer>()
.ForMember(x => x.Id, a => a.Ignore());


AutoMapper качается отсюда https://github.com/AutoMapper/AutoMapper
или ставится через Nuget (предпочтительней) http://nuget.org/packages/automapper


В 3 варианте:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
        // ВМЕСТО

        public Document Passport
        {
             get { return (Documents != null) ? Documents.Where(d => d.DocumentType == 1).FirstOrDefault() : null; }
        }

        // ВОТ ТАК

        public Document GetPassport()
        {
             return (Documents != null) ? Documents.Where(d => d.DocumentType == 1).FirstOrDefault() : null;
        }
...
Рейтинг: 0 / 0
Модели
    #38216273
evgen12345
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
hVostt,

Большое спасибо!

Значит третий вариант тоже живой? И можно его применять.
...
Рейтинг: 0 / 0
Модели
    #38216459
evgen12345
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вопрос с наследованием и размещением логики так и не прояснился.
Кто подскажет?
...
Рейтинг: 0 / 0
Модели
    #38216542
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
evgen12345Вопрос с наследованием и размещением логики так и не прояснился.
Нонче некто hVostt говорит, что наследование - зло, нужно юзать DI :)
...
Рейтинг: 0 / 0
Модели
    #38217615
evgen12345
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
МСУevgen12345Вопрос с наследованием и размещением логики так и не прояснился.
Нонче некто hVostt говорит, что наследование - зло, нужно юзать DI :)

И как этого зверя применить на текущем примере?
...
Рейтинг: 0 / 0
Модели
    #38217779
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
evgen12345И как этого зверя применить на текущем примере?
hVostt - это мембер, его нельзя применить на текущем примере.
...
Рейтинг: 0 / 0
Модели
    #38217804
evgen12345
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
МСУevgen12345И как этого зверя применить на текущем примере?
hVostt - это мембер, его нельзя применить на текущем примере.

я имел ввиду DI
...
Рейтинг: 0 / 0
Модели
    #38222819
evgen12345
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Продолжу рассуждения.

Логика получения данных из БД в контроллере - зло. Значит есть слой доступа к данным (где то там, например в отдельной сборке). Как правило такой слой содержит CRUD методы для сущностей. В моем понимании это методы:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
public long InsertCustomer(Customer customer)
{
}
// или метод должен иметь следующую сигнатуру 
public long InsertCustomer(String shortName, String Name1, .....)
{
}

public void DeleteCustomer()
{
}

public void UpdateCustomer()
{
}

public Customer GetCustomerById(long id)
{
}

public ICollection<Customer> GetCustomerByParam(.....)
{
}

// тоже самое по документам
......



Вопрос - должен ли слой доступа к данным содержать метод
Код: c#
1.
public CustomerModel GetCustomerModelById(long id) {....}


?

Если нет, то где располагается логика получения этой модели?
...
Рейтинг: 0 / 0
Модели
    #38222823
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
evgen12345,
что то не могу понять потуга..
public CustomerModel GetCustomerModelById(long id) {....}
Вы наверное это имели в виду
public T GetCustomerModelById<T>(Object key) {....}
...
Рейтинг: 0 / 0
Модели
    #38223540
МСУ_МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
evgen12345,

то, что ты написал, это слой датасервиса (репозитория), в нем нечего делать моделям представления. Для маппинга модели данных на модель представления импользуй маппер. Маппить должен контроолер - дергать репозиторий, результат намапливать на вью модель.
...
Рейтинг: 0 / 0
Модели
    #38223639
МСУ_МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
тут про мапперы
...
Рейтинг: 0 / 0
Модели
    #38230040
evgen12345
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Где-то в степиevgen12345,
что то не могу понять потуга..
public CustomerModel GetCustomerModelById(long id) {....}
Вы наверное это имели в виду
public T GetCustomerModelById<T>(Object key) {....}

Потуг простой - хочу понять архитектуру или концепцию построения приложений на ASP.NET MVC.
Просто до этого я не занимался созданием веб приложений и пока изучаю для себя, но впереди есть перспектива принять участие в интересном мне проекте, вот и разбираюсь.

Мне не понятно где должна быть логика склеивания модели в модель-вью?
С одной стороны у меня есть репозиторий который мне вернет клиента, потом мне нужно сходить за документами (другой репозиторий) и дополнить модель-вью паспортом - так?
С другой стороны эти лишние походы в базу не оптимальны и что мешает получить сразу необходимые данные - но тогда репозиторий должен мне предоставить зоопарк методов для каждой вью модели?
Или репозиторий должен быть для модель-вью?

Пример .
от customer получим два наследника Legal и Person у них добавятся уникальные поля. Необходимо отображать список всех клиентов или результат поиска по имени в виде:
Код: c#
1.
CustomerId | ShortName | Document.


где документ это серия и номер паспорта для Person или другого документа удостоверяющего личность, а для Legal это номер и дата выдачи свидетельства о регистрации (ОГРН).

Если решать задачу в лоб то не проблема - создам соответствующую модель-вью и в документ буду записывать данные в зависимости от типа клиента (тип клиента служебное поле). Но как это спроектировать правильно? где должна быть эта логика и как будет выглядеть депозиторий в этом случае?

Спасибо.
...
Рейтинг: 0 / 0
Модели
    #38230094
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
evgen12345,
если модель включает много сущностей, зараяжайте модель в момент создания инжектировав в нею - что там у вас -тип клиента
если у вас как вы говорите получается зоопарк методов, а оно вам надо, можно применить "композицию" в модели - мувице это поддерживает, тогда весь репозитарий сведется к классическому виду.
...
Рейтинг: 0 / 0
Модели
    #38230103
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
evgen12345,
вот примерно
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
 public class CustomerModel
    {
        public тип клиента id {get;set;}
        public CustomerModel()
       {
       }

        public CustomerModel(тип клиента id)
       {
            this.id=id;
       }
        public Customer _customer{ get; set; }
        public Document _passport{ get; set; }
    }


И нужен ли тут репозитарий......
...
Рейтинг: 0 / 0
Модели
    #38230106
evgen12345
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Где-то в степиevgen12345,
вот примерно
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
 public class CustomerModel
    {
        public тип клиента id {get;set;}
        public CustomerModel()
       {
       }

        public CustomerModel(тип клиента id)
       {
            this.id=id;
       }
        public Customer _customer{ get; set; }
        public Document _defaultDocument{ get; set; }
    }


И нужен ли тут репозитарий......

Вот я и пытаюсь понять - нужен ли репозиторий и собственно DI.
...
Рейтинг: 0 / 0
Модели
    #38230122
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
evgen12345,
да как бы надо смотреть на комплексно, в данном случае не вижу смысла,
контейнер тоже смотреть комплексно, или как старший скажет.
ведь код по созданию объекта модели в контроллере в любом случае придется писать, сам объект от святого духа не возьмется
в данном случае у вас просто CustomerModel cm=new CustomerModel(тип клиента)
а с контейнором вам придется прицеплять контейнер к проекту, заряжать его типами, и при вызове резолве все равно запихивать
туда тип клиента ( или при зарядке), из за одного инжекта тащить di ?
Можете сами написать di, это не сложно, создается делегат грубо говоря под каждый тип при зарядке, а потом в коде
вызывается этот делегат в зависимости от типа , этот кусок кода исполняется и выплевывается готовый объект.
Шаманства никакого, трюк давно известный..
...
Рейтинг: 0 / 0
Модели
    #38230232
evgen12345
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Где-то в степиevgen12345,
да как бы надо смотреть на комплексно, в данном случае не вижу смысла,
контейнер тоже смотреть комплексно, или как старший скажет.
ведь код по созданию объекта модели в контроллере в любом случае придется писать, сам объект от святого духа не возьмется
в данном случае у вас просто CustomerModel cm=new CustomerModel(тип клиента)
а с контейнором вам придется прицеплять контейнер к проекту, заряжать его типами, и при вызове резолве все равно запихивать
туда тип клиента ( или при зарядке), из за одного инжекта тащить di ?
Можете сами написать di, это не сложно, создается делегат грубо говоря под каждый тип при зарядке, а потом в коде
вызывается этот делегат в зависимости от типа , этот кусок кода исполняется и выплевывается готовый объект.
Шаманства никакого, трюк давно известный..

Это всего лишь пример который я придумал. Писать самому di смысла не вижу, если только ради интереса - но мой интерес сейчас ASP.NET MVC по этому при необходимости воспользуюсь готовыми реализациями.
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / Модели
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]