Форум программистов, компьютерный форум, киберфорум
C#: ASP.NET Core
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.78/18: Рейтинг темы: голосов - 18, средняя оценка - 4.78
1519 / 462 / 126
Регистрация: 09.01.2018
Сообщений: 1,094
1

ASP.NET Core MVC - Создание коллекций объектов

09.01.2018, 21:24. Показов 3171. Ответов 16
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте всем!
Я начинающий веб разработчик. Опыт минимальный, написал несколько простых магазинов. Пробую найти подходящий способ для создания объектов, содержащих в своих полях коллекции других объектов. Поясню суть проблемы. Для простоты, пусть это будет телефонная книга, и пусть это будут следующие объекты:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Person
{
    int Id
    string FirstName
    string LastName
 
    //nav
    virtual ICollection<Phone> Phones
}
 
class Phone
{
    int Id
    string PhoneNumber
 
    //nav
    int PersonId
    virtual Person Person 
}
Задача проста, создать объект Person с заданными пользователем именем, фамилией и несколькими номерами телефонов и внести новые объекты в базу данных. Думаю, будет удобным, если получение всех данных и сбор коллекции телефонов, будет происходить на одной странице. Полей с коллекциями, конечно же может быть куда больше, например фото, мейлы. Но для простоты я ограничился одним таким полем с телефонами.

В целом к решению такой задачи, у меня пока имеются три варианта.

1. Для каждого объекта создать свой контроллер. Использовать layout с tabs для каждой из коллекций главного объекта, генерировать ссылки, ведущие на нужный контроллер с параметром personId. А в методах котроллеров создавать соответствующие объекты с указанным personId и возвращать View c описанным layout. DRY соблюдается, каждый контроллер знает как работать со своим объектом. Но, имеет место хождение с контроллера на контроллер (многочисленные обращения к серверу). Плюс нужно всегда передавать personId, а значит он всегда должен где то быть и каждый метод каждого котроллера, должен его в это что то каждый раз помещать. Работает, но берут сомнения, рационален ли такой подход.

2. Использовать один контроллер - Persons. Поля коллекций добавлять через JS, для получения всех данных использовать одну страницу (можно с табами для удобства). Все данные получить в один метод Create и создать объект сразу с коллекциями. В этом случае нет обращения к другим котроллерам. Но сам котроллер Persons перегружен методами не относящимися к нему напрямую (содерджит CRUD других объектов). Также объект Phone может понадобиться в другом месте приложения. И тогда неизбежно наступит повтор кода.

3. Использовать предыдущий подход, но вынести методы CRUD (точнее их содержимое) для объектов коллекций в сервисы. Тогда контроллеры будут обращаться к сервисам своих объектов. Create - обращение к сервису, сохранение, возврат View. Тут нет повтора кода, но меня берут сомнения, правильно ли это.

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

Спасибо.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
09.01.2018, 21:24
Ответы с готовыми решениями:

Разница между ASP.NET Core 2, ASP.NET Core MVC, ASP.NET MVC 5 и ASP.NET WEBAPI 2
Здравствуйте. Я в бекенд разработке полный ноль. В чем разница между вышеперечисленными...

Какая разница между ASP .Net Core и ASP .Net Core MVC?
Какая разница между ASP .Net Core и ASP .Net Core MVC? Или я может что-то не так понял? И...

ASP.NET MVC или ASP.NET Core
Добрый вечер, подскажите что лучшие изучать ASP.NET MVC или ASP.NET Core ? Как я понимаю ASP.NET...

Уведомления в ASP.NET MVC Core
Добрый день. Мне для сайта необходимо сделать уведомления о том, что та или иная запись была...

16
7 / 7 / 1
Регистрация: 26.04.2013
Сообщений: 34
10.01.2018, 06:55 2
Вынеси логику из контроллера и используй репозиторий и паттерн UnitOfWork.
https://metanit.com/sharp/mvc5/23.3.php

Контроллера одного достаточно.
0
653 / 589 / 171
Регистрация: 17.07.2012
Сообщений: 1,670
Записей в блоге: 1
10.01.2018, 17:25 3
escoult, мыслите от модели:
Созданием, удалением и редактированием модели Person, в том числе добавление телефонов для пользователя - для PersonController.
Созданием, удалением и редактированием модели Phone, в том числе добавление пользователья для телефона - для PhoneController.
Разница между добавление телефонов для пользователя и добавление пользователья для телефона в том, какую модель вы редактируете.
0
1519 / 462 / 126
Регистрация: 09.01.2018
Сообщений: 1,094
11.01.2018, 00:14  [ТС] 4
cunami
UnitsOfWork я не использую. Использую репозиторий с Generic Methods. Собственно, в этом случае, необходимость в UnitsOfWork отпадает.

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

Добавлено через 11 минут
Cupko
То же думал над этим. Но не додумал до конца. Как быть с вьюшками? Моделей две, какую вьюшку будет возвращать каждый контроллер? По идее, каждый свою. Но страница редактирования у меня одна. По крайней мере, для пользователя это должно выглядеть так. Открыл он какой то Person Details, хочет отредактирорвать. Но я не знаю, что он захочет редактировать. Может персональные данные, а может телефоны. Какую форму ему подсовывать? На странице, сколько бы у меня их не было, Submit все равно один. Как тогда должна выглядеть эта вьюшка, чтобы все поля модели были доступны для редактирования? Или все же по ссылкам его отправлять на контроллер той модели, которая редактируется?
0
2735 / 2041 / 380
Регистрация: 22.07.2011
Сообщений: 7,731
11.01.2018, 13:11 5
Цитата Сообщение от cunamy Посмотреть сообщение
паттерн UnitOfWork.
- это не паттерн , а антипаттерн от какого то индуса , один фигню написал , другие не думая подхватили.
Но страница редактирования у меня одна
ну так и вью.модель у нее одна, косвенно связанная с моделями данных. , т.е редактируется вью.модель , а затем раскидываете результат по нужным моделям данных и репозиториям.
0
Warrior
500 / 427 / 177
Регистрация: 23.11.2014
Сообщений: 932
11.01.2018, 14:03 6
Цитата Сообщение от sau Посмотреть сообщение
- это не паттерн , а антипаттерн от какого то индуса , один фигню написал , другие не думая подхватили.
Да ну быть не может. Microsoft так например не считает, со своей реализацией UnitOfWork в виде DbContext https://github.com/aspnet/Enti... ext.cs#L27
1
Эксперт .NET
12078 / 8387 / 1281
Регистрация: 21.01.2016
Сообщений: 31,595
11.01.2018, 14:47 7
Цитата Сообщение от sau Посмотреть сообщение
это не паттерн , а антипаттерн от какого то индуса
Зря вы так.
1
2735 / 2041 / 380
Регистрация: 22.07.2011
Сообщений: 7,731
11.01.2018, 20:14 8
Цитата Сообщение от _exp10der_ Посмотреть сообщение
Да ну быть не может. Microsoft так например не считает, со своей реализацией UnitOfWork в виде DbContext
Ну ладно , тут вероятно можно по разному понимать реализацию паттерна , у мелкософта я не увидел криминала , а вот вариант по ссылке на метанит мне совершенно не понравился.
Если следовать определению:
Обслуживает набор объектов, изменяемых в бизнес-транзакции (бизнес-действии) и управляет записью изменений и разрешением проблем конкуренции данных.
зачастую реализация сводится к обычному сервису данных , который инкапсулирует в себе логику работы с интерфейсами различных репозиториев.


И кстати , кто сказал что в майкрософт индусы не работают ? ) , приведенный пример реализации на метаните уж очень узконаправленный , сразу несколько сущностей тесно связываются общим Db контекстом ,в итоге теряем гибкость и возможность изменить для этой группы тип репозитория (скажем не SQL и не EF) , в то время как паттерн репозитория с этой целью и реализуется. Его конечно можно допилить , реализуя абстрактный контекст и т.п , но это все проще решается.
0
7 / 7 / 1
Регистрация: 26.04.2013
Сообщений: 34
11.01.2018, 21:23 9
Цитата Сообщение от sau Посмотреть сообщение
Ну ладно , тут вероятно можно по разному понимать реализацию паттерна , у мелкософта я не увидел криминала , а вот вариант по ссылке на метанит мне совершенно не понравился.
под статьей метаинт указывает ссылку откуда он взял реализацию паттерна https://docs.microsoft.com/en-... pplication

Добавлено через 47 минут
Я у себя раньше использовал вот такую релизацию от Julia Lerman, очень удобно тестить

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
    public class UnitOfWork<TContext> : IUnitOfWork where TContext:IContext, new()
    {
        private readonly IContext _context;
 
 
        public UnitOfWork()
            :this(new TContext())
        {
        }
 
        public UnitOfWork(IContext context)
        {
            _context = context;
        }
        public int Save()
        {
            return _context.SaveChanges();
        }
 
        public IContext Context
        {
            get { return _context; }
        }
 
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
 
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
                if (_context != null)
                    _context.Dispose();
        }
    }
0
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
12.01.2018, 22:31 10
А я использую https://github.com/mehdime/DbContextScope
Тихо мирно у себя в углу считаю это "серебряной пулей" в плане доступа к данным, у автора гигантская статья в которой описаны все возможные варианты их плюсы и минусы (я сам половину из них использовал и согласен)
он учел все "наивные" реализации IRepository и IUnitOfWork которым забит интернет и несколько прочих вещей и вариантов (да и я тоже)

бесконечно гибкая вещь, хоть 2-3 контекста, хоть репозитории(идеально вливаются), хоть напрямую используй контекст в кастомных сервисах


так же годится как для для специальных мест где критична производительность, так и для специальных мест где критична транзакционность - ногу отстрелить не дает (поначалу бесит правда, но ведь он прав(!!) 2 save быть не должно никогда)

а ну и да я уже 3 раза использовал либу в боевых проектах, 2 кровавый энтерпрайз 1 домашний, либа и ее идеология выдержала всё без каких-либо серьезных проблем, хоть веб, хоть обычные окна
2
2735 / 2041 / 380
Регистрация: 22.07.2011
Сообщений: 7,731
13.01.2018, 15:58 11
Цитата Сообщение от m0nax Посмотреть сообщение
ну и опять же , решаются узкие вопросы касательно EF и связанного с ним контекста , тем самым нарушая идеологию шаблона репозиториев. Они на то и абстрагированы интерфейсом , что реализация может быть для каждой сущности своя (БД , файл , облако) , и никакая узконаправленная специфика в виде контекста на этом уровне присутствовать не должна.
Тут , при необходимости , должен использоваться механизм распределенной транзакции , реализация которого уже зависит от обстоятельств.

А вот внтури уже конкретной реализации репозитория - который совсем не обязательно может быть элементарным , уже можно применять всякие контекстно зависимые штуки вроде DbContextScope или UnitOfWork, там они правомерны т.к решают задачу в своем контексте.
0
Эксперт .NET
12078 / 8387 / 1281
Регистрация: 21.01.2016
Сообщений: 31,595
13.01.2018, 16:02 12
sau, как-то я с вами не согласен. Идея "контекста" ни как не диктует способ хранения данных.
0
2735 / 2041 / 380
Регистрация: 22.07.2011
Сообщений: 7,731
13.01.2018, 16:15 13
Идея "контекста" ни как не диктует способ хранения данных.
В общем случае возможно и нет , я говорю по конкретно приведенным примерам , где есть четкая зависимость от вполне конкретного типа контекста. А если смотреть на контекст в общем , то это тоже такой непонятный отросток , Который нужен далеко не везде , тобишь из общего интерфейса репозитория , какой либо интерфейс контекста вообще можно исключить.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class DataService
{
   IRepsitory<Entity1> rp1 //облако
   IRepsitory<Entity2> rp2 //файл
   IRepsitory<Entity3> rp3 //БД
 
   public void InsertMethod(ComplexModel Model)  
   {
         BeginTransaction()//открываем распределенную транзакцию
         rp1.Insert(Model.Data1);
         rp2.Insert(Model.Data2);
         rp3.Insert(Model.Data3);
         CommitTransaction();
   }
 
}
0
Эксперт .NET
12078 / 8387 / 1281
Регистрация: 21.01.2016
Сообщений: 31,595
13.01.2018, 16:21 14
sau, ну, "контекст" выступает в роли контейнера репозиториев. Совершенно не обязательно, что он (контекст) должен быть в одном лице. То, что он не везде нужен - спору нет. Это очередная абстракция для более-менее сложных проектов.

Но сама идея контекста не диктует правила хранения данных
0
2735 / 2041 / 380
Регистрация: 22.07.2011
Сообщений: 7,731
13.01.2018, 17:10 15
Цитата Сообщение от Usaga Посмотреть сообщение
sau, ну, "контекст" выступает в роли контейнера репозиториев.
по вашим словам и по вышеизложенному , получается , что он группирует схожие по принципу работы репозитории , скажем DbContext группирует SQL репозитории. А если репозитории принципиально разные - будет несколько разных контекстов , но которые все равно может понадобиться выполнить в рамках одной транзакции , и в таком случае , вероятно , смысл дополнительной абстракции в виде контекста пропадает. В общем , все зависит от решаемой задачи , как всегда.

Цитата Сообщение от sau Посмотреть сообщение
"контекст" выступает в роли контейнера репозиториев.
Все же я немного не понял этот момент. , скорее наоборот , контекст присутствует как частный случай в одной из конкретной реализации интерфейса репозитория , для его внутренних нужд , или мы о каком контексте ведем речь ? ) , а вот предложенная выше реализация UnityOfWork работает только с группой репозиториев объедененных контекстом., на что я и обратил внимание с самого начала , с какой стати интерфейсы репозиториев вообще должны иметь какую либо привязку к "контексту". Ну , конечно , понятно какая там задача решается как и в прочих примерах , но это все очень узконаправленно , ограничено только репозиториями с контекстом , или еще хуже SQL репозиториями. Ладно , похоже пошли по кругу.
0
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
13.01.2018, 17:17 16
ну и опять же , решаются узкие вопросы касательно EF и связанного с ним контекста , тем самым нарушая идеологию шаблона репозиториев. Они на то и абстрагированы интерфейсом , что реализация может быть для каждой сущности своя (БД , файл , облако) , и никакая узконаправленная специфика в виде контекста на этом уровне присутствовать не должна.
какая еще специфика? как раз наоборот репозитории создаются самые чистейшие по интерфейсам

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class UserRepository : IUserRepository
{
    private readonly IAmbientDbContextLocator _contextLocator;
 
    public UserRepository(IAmbientDbContextLocator contextLocator)
    {
        if (contextLocator == null) throw new ArgumentNullException("contextLocator");
        _contextLocator = contextLocator;
    }
 
    public User Get(Guid userId)
    {
        return _contextLocator.Get<MyDbContext>.Set<User>().Find(userId);
    }
}
то есть никто не мешает создать второй репозиторий который будет получать из файла или облака, причем с тем же интерфейсом User Get(Guid userId), ведь вся завязка на БД происходит именно в конструкторе как деталь реализации
а созданием контекста и сохранением/коммитом управляет внешний код, который выше по стеку (обычно на самой вершине)
естественно там могут быть и распределенные транзакции и что еще нужно
0
2735 / 2041 / 380
Регистрация: 22.07.2011
Сообщений: 7,731
13.01.2018, 17:59 17
Тут уже столько понаписали , что начинается подмена понятий ). - нужно внимательно каждый пост прочитать , с самого начала.
Ото начали за здравие закончили за упокой.

Цитата Сообщение от m0nax Посмотреть сообщение
какая еще специфика? как раз наоборот репозитории создаются самые чистейшие по интерфейсам
ну я как раз это и имел ввиду , касательно интерфейсов репозиториев , они должны быть чистейшими , без специфических зависимостей.

Цитата Сообщение от m0nax Посмотреть сообщение
а созданием контекста и сохранением/коммитом управляет внешний код, который выше по стеку (обычно на самой вершине)
естественно там могут быть и распределенные транзакции и что еще нужно
с такой постановкой согласен.

П.С
В приведенной Вами ссылке , в одном из интерфейсов встречается такая штука
TDbContext Get<TDbContext>() where TDbContext : DbContext;
где DbContext - это ограничивающая зависимость. , т.е библиотечка применима для определенного круга репозиториев.
Да , ваш пример репозитория вполне определенно использует DbContext , и может это делать не вынося этот момент на более общий интерфейс. Только , это все немного не в ключе обсуждаемого.


Но , возвращаясь к нашим баранам , с того , с чего начали:
C#
1
2
3
4
5
6
7
public class UnitOfWork : IDisposable
{
    private OrderContext db = new OrderContext();
    private BookRepository bookRepository;
    private OrderRepository orderRepository;
....
}
Может , все же , ближе к конкретике , поясните мне смысл этой конструкции ?
Во-первых , почему не IRepository<book> bookRepository ?, - какой смысл в шаблоне репозитория если мы не можем подменить реализацию ?
А если тут подставить интерфейс IRepository<book> , то мы не сможем работать через OrderContext db , поскольку на уровне интерфейса мы не имеем обязательств юзать какой либо контекст. Короче , очень сомнительная реализация.
0
13.01.2018, 17:59
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
13.01.2018, 17:59
Помогаю со студенческими работами здесь

Работа с Excel в ASP.NET MVC Core
Подскажите как читать excel файлы в ASP.NET MVC Core. Пробовал различные библиотеки, все выдавали...

Ошибка List`1 IEnumerable [ASP.Net Core MVC]
Всем привет! Изучаю ASP .Net Core по книге Фримана Pro ASP.Net Core MVC и что-то не получается:...

Как опубликовать ASP.Net Core MVC в Plesk?
Здравствуйте уважаемые программисты! Подскажите пожалуйста как опубликовать веб сайт написанный в...

ASP.NET Core. Старт - что нужно знать, чтобы стать ASP.NET Core разработчиком?
Попалось хор краткое обзорное видео 2016 года с таким названием - Что нужно знать, чтобы стать...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru