Jak korzystac z repozytorium w kontrolerze

Odpowiedz Nowy wątek
2019-01-12 10:34
0

Czytam kolejna książkę o ASP NET MVC5 i po raz kolejny jest przykład ze pobieranie danych odbywa się w kontrolerze. Przewija sie to w wielu ksiazkach i tutorialach, mamy np:

 public class StudentController : Controller
    {
      private readonly IStudentRepository repository;

        public StudentController(IStudentRepository repo)
        {
            repository = repo;
        }
public ViewResult Edit(int id)

 {
            Student student = repository.Students.FirstOrDefault(s => s.StudentId == id);
            return View(student);
        }

//...
}

To jest bardzo prosty przykład, ale jak to będzie wygladało jak bedziemy chcieli pobrac i zwrocic dane z wielu repozytoriów, bedzie totalny chaos. Sadze ze nie tak powinno to wygladac. Według mnie powinien tam byc przekazywany ViewModel czyli ja bym to zrobil tak:

 public ViewResult Edit(int id)
        {
            StudentService studentService = new StudentService();
            StudentViewModel studentViewModel = studentService.GetStudentViewModel(id);
            return View(studentViewModel);
        }

Tylko w takim przypadku zastanawiam się jak z kontrolera (i czy w ogóle tak to zrobić) przekazywać repozytorium do studentService. Czy zrobić po prostu

public class StudentService
    {
        public StudentViewModel GetStudentViewModel(IStudentRepository repository, int id)
        {
            //pobieranie danych
            //mapowanie na StudentViewModel
            //zwracanie StudentViewModel
        }

        //...
    }

Tylko wtedy pojawia się problem bo StudentViewModel może mieć tez elementy z innych repozytoriów (ITeachersRepository, ILectureRepository)

Jak to ładnie ugryźć?

Pozostało 580 znaków

2019-01-12 11:45
1

Wywal to reposytorium i korzystaj bezpośrednio z Dbcontextu . Ja odkąd robię w asp mvc jeszcze nigdy nie używałem repo, Moim zdaniem jest nie potrzebne

Pozostało 580 znaków

2019-01-12 11:59
0

@szydlak: a mógłbyś pokazać jak to by wyglądalo poprawnie na moim przykładzie? DbContext powinien być przekazywany z kontrolera do StudentService?

Pozostało 580 znaków

2019-01-12 12:02
3

Dbcontext i serwisy powinny być wstrzykiwane. Serwis do kontrolera a context do serwisu. Autofac ci w tym pomoże

Pozostało 580 znaków

2019-01-12 12:08
3

@goodfather: Gratuluję. Zrozumiałeś coś, co wielu osobom sprawia trudność.
Jeszcze tylko mentalnie się odklej od tezy, że kontroler ma cokolwiek wspólnego z bazą danych.
W prostym przypadku ma być jak u Ciebie. Kontroler wywołuje jakieś metody serwisu i to serwis ma dostęp do bazy danych (zwykle wystarcza DBContext, bez jakichś niepotrzebnych warstw pośrednich, nazywanych często repozytorium).

Do zastanowienia czy viewmodel dla edycji to jest ten sam co do wyświetlenia. Może się okazać, że formularz edycji musie zawierać nieco inne dane niż wyświetlenie danych studenta i wtedy przydałby się osobny viewmodel dla edycji i w serwisie sobie to przetwarzasz.

W książkach o MVC tak piszą bo to nie książki o architekturze aplikacji tylko o frameworku MVC.

Pozostało 580 znaków

2019-01-12 15:42
0

@szydlak: @jacek.placek a jeszcze takie pytanie. Mam model Student

public class Student
    {
        public int StudentId { get; set; }
        public string Name { get; set; }
        public string LastName { get; set; }
        public DateTime DateOfBirth { get; set; }
        //...
    }

chcę wyświetlić teraz dane tego studenta zeby uzytkownik mogl je edytowac. Tworze sobie wiec ViewModel

public class StudentViewModel
    {
        public int StudentId { get; set; }  //powinno tu byc czy nie?
        public string Name { get; set; }
        public string LastName { get; set; }
        public DateTime DateOfBirth { get; set; }
        //...
    }

Teraz pytania:

  1. czy w ViewModelu powinno sie znaleźć StudentId (sądze ze gdy jest to klucz z bazy to nie powinno a jesli to np numer indeksu studenta to powinno. Wiec nawet jak uzywam numeru indeksu jako klucza w tabeli to dałbym go do Viewmodelu.)
  2. gdzie wstawiac DataAnnotations? W modelu czy w viewmodelu?
edytowany 6x, ostatnio: goodfather, 2019-01-12 15:45

Pozostało 580 znaków

2019-01-12 20:02
1
  1. Tak. Dla udaru będzie konieczne. Dla insert nie przeszkadza.

  2. Dla viewmodel jeśli to adnotacje związane np. z walidacja, etykietą itp. Q modelu jeśli to adnotacje związane ze schematem db ale tu polecam FluentAPI.

Dla updatu. Dalej nie wiem jak wyłączyć korekte w telefonie. - jacek.placek 2019-01-12 23:09

Pozostało 580 znaków

2019-01-12 21:40
0

Napisałem takie klasy (odzwierciedlaja one tabele jakie mam w bazie) czy poprawnie to wygląda, głównie chodzi mi o to ze w tym przypadku chce edytować studenta, ale chcialbym tez miec możliwość zmiany pokoju i biurka przypisanego do tego studneta, ewentualnie jesli wczesniej nie było takiego pokoju lub biurka to zeby został zrobiony odpowiedni insert do tabel Room i Desk. Chodzi mi tez o zasadnosc przekazywania RoomId i DeskId do viewmodelu.

public class Student
    {
        public int StudnetId { get; set; }
        public string Name { get; set; }
        public string Lastname { get; set; }
        public DateTime DateOfBirth{ get; set; }

        public int RoomId { get; set; }
        public int DeskId { get; set; }
    }

    public class Room
    {

        public int RoomId { get; set; }
        public int Number { get; set; }
        public string Description { get; set; }
        public int Capacity { get; set; }
    }

    public class Desk
    {
        public int DeskId { get; set; }
        public string Description { get; set; }
    }

//viewmodel przekazywany do widoku edycji studenta
    public class StudentEditViewModel
    {
        public int StudnetId { get; set; }
        public string Name { get; set; }
        public string Lastname { get; set; }
        public DateTime DateOfBirth { get; set; }
        public int RoomId { get; set; }
        public int RoomNumber { get; set; }
        public string RoomDescription { get; set; }
        public int RoomCapacity { get; set; }
        public int DeskId { get; set; }
        public string DeskDescription { get; set; }
    }

Czy nawet jeśli przekazuje pola Id do widoku, to powinienem je jakos ukrywać?

edytowany 2x, ostatnio: goodfather, 2019-01-12 21:42

Pozostało 580 znaków

2019-01-12 22:07
0

Dodaj sobie do Studenta public Room Room {get;set;} i public Desk Desk {get;set;}.
Jeśli przekazujesz do widoku ID studenta to dajesz to np do ukrytego inputa

Pozostało 580 znaków

2019-01-12 22:12
0

Jak to w końcu jest z jechaniem na czystym contexcie? (@Aventus)

edytowany 3x, ostatnio: WeiXiao, 2019-01-12 22:39

Pozostało 580 znaków

2019-01-12 23:23
1

Odpowiedz jest prosta- to zalezy ;) Jesli piszemy zwyklego CRUDa to dla czego by nie uzywac bezposrednio contextu (chociaz nie w kontrolerach, o tym za chwile). Natomiast przy bardziej rozbudowanych aplikacjach moim zdaniem nie ma nic zlego w stosowaniu repozytoriow (czy jakkolwiek to nazwac, moze byc store/MyUnicornStorage/cokolwiek), a wrecz przeciwnie. Pomijajac juz fakt ze pozwala to calkowicie oddzielic warstwe infrastruktury od domeny (EF to tez swojego rodzaju taka warstwa, a raczej cos pomiedzy), taka abstrakcja ulatwia wyrazne kontrolowanie tego co i jak jest modyfikowane oraz wyciagane z bazy danych.

Co do samego uzywania repozytoriow czy tez contextu w kontrolerach, jest to moim zdaniem bledne. Kontrolery powinny byc "glupie" i jedynie przekazywac polecania- albo za pomoca serwisow albo przy zastosowaniu podejscia command-handler (MediatR). Jesli mamy do wyciagniecia bardziej skomplikowany model- tak jak opisane w tym watku- to mozemy miec do tego oddzielna metode w naszym repozytorium. Podsuwa to kwestie tego czy ogolne podejscie do problemu jest wlasciwe. Moze nalezalo by miec oddzielny modul odpowiedzialny za budowanie modelu widoku? Np. repozytorium wyciagajace dane z tabeli ktora jest niczym innym jak view modelem, zbudowanym ze zmian dokonanych do wielu encji w systemie. Cos takiego mozna osiagnac przy zastosowaniu eventow (lub np. notifications w MediatR). Za kazdym razem gdy dochodzi do interesujacej nas zmiany, w system zostaje wyslany event ktorych moze byc przetworzony przez dowolna liczbe subskrybentow. Takim subskrybentem moze byc wlasnie modul odpowiedzialny za budowanie (i posrednio za zapisywanie do bazy) widoku.


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0