Dependency Injection z Unit Of Work

Odpowiedz Nowy wątek
2018-11-12 04:10
Wielki Karp
0

Cześć czy używając w projekcie UoW oraz Dependency Injection powinienem wstrzykiwać do kontrolera cały obiekt UnitOfWork a potem go przekazywać do serwisów zamiast pojedynczych repozytoriów? Może lepszym rozwiązaniem jest wstrzyknięcie UoW do konstruktora kontrolera i przypisanie go do pola prywatnego natomiast w akcji przekazanie już tylko danego repozytorium do serwisu. W takim wypadku wywołanie zapisu musiałoby się odbywać z poziomu akcji, a nie w serwisie - co jest chyba średnim rozwiązaniem.

Co o tym myślicie?

Pozostało 580 znaków

2018-11-12 07:59
1

ani jedno ani drugie

wstrzykuj klase ktora zarzadza daną funkcjonalnoscia do kontrolera. Ta klasa niech posiada w konstruktorze UOW od DI i tam decydujesz kiedy zapisac zmiany z UOW i z jakich repozytoriow korzystac.

Kontroller nie ma nic zapisywac ani nie ma wiedziec nic o logice biznesowej

Pozostało 580 znaków

2018-11-12 09:34
._.
0

Kluczowym powodem implementacji UOW jest decydowanie o czynnościach związanych z zatwierdzaniem transakcji jak problem współbieżności. Poza tym są trzy podstawowe sposoby implementacji UOW ty prawdopodobnie mówisz o "Unit Of Work Controller" w najgłupszej postaci, czyli mutancie, który jest nakładką na EF i "repositories" (architektura z MS albo pakiet wzorców Dr. Freemana ma się rozumieć). Niektórzy robią sobie takiego wrapa na sesje ORM'a i ma to sens, jeśli chcesz używać repository w wariancie "Repository typu kolekcja" zamiast "trwały magazyn". Ty prawdopodobnie potrzebujesz tylko serwisu, który operuje na ORM jako taki Data Gate czy DAO. Controller to zupełnie inna bajka to służy do czego innego niż serwisy - fasady z niższego poziomu.

edytowany 2x, ostatnio: ._., 2018-11-12 09:48

Pozostało 580 znaków

2018-11-12 13:02
Wielki Karp
0
fasadin napisał(a):

ani jedno ani drugie

wstrzykuj klase ktora zarzadza daną funkcjonalnoscia do kontrolera. Ta klasa niech posiada w konstruktorze UOW od DI i tam decydujesz kiedy zapisac zmiany z UOW i z jakich repozytoriow korzystac.

Kontroller nie ma nic zapisywac ani nie ma wiedziec nic o logice biznesowej

Czy można liczyć na podesłanie jakiegoś przykładu z taki kodem? Może jakiś projekt na githubie.

Co jest powodem implementacji twojego UOW, a raczej co ona zawiera? - ._. 2018-11-12 13:22

Pozostało 580 znaków

2018-11-12 13:52
Wielki Karp
0
._. napisał(a):

Co jest powodem implementacji twojego UOW, a raczej co ona zawiera?

Piszę projekt wolnym czasie w którym chciałbym wykorzystać jak najwięcej wzorców tak by struktura była dobrze zaprojektowana, oraz żeby nauczyć się jak najwięcej.

Wiem że toczy się dyskusja czy repozytorium jest w ogóle potrzebne i czy jest sens używania UoW.
W projekcie który piszę (nie będzie on jakiś skomplikowany) pewnie nie ma konieczności używania tych wzorców, chociaż z doświadczenia powiem że wolę mieć jasno wyznaczone miejsce w którym zdefiniowane są wszystkie zapytania do bazy, a nie rozwalone po całej aplikacji poprzez dobijanie się do DbContextu i tworzenie po parę razy tych samych zapytań. Nigdy wcześniej nie używałem UoW(w pracy problem był rozwiązywany przez DbContext.Save()).

Po przeczytaniu paru artykułów zdecydowałem się na użycie niegenerycznego repozytorium oraz UoW.

Tutaj zawartość moich klas:

    public interface IUnitOfWork : IDisposable
    {
        IUserRepository Users { get; }
        IRequestRepository Requests { get; }
        ITimeSlotRepository TimeSlots {get; }
        void Complete();
        Task CompleteAsync();
    }
 public class UnitOfWork : IUnitOfWork
    {
        private readonly ManageItDbContext _context;

        public UnitOfWork(ManageItDbContext context)
        {
            _context = context;
            Users = new UserRepository(_context);
            Requests = new RequestRepository(_context);
            TimeSlots = new TimeSlotRepository(_context);
        }

    //zawartość powinna mieć wszystkie repozytoria

        public IUserRepository Users { get; private set; }
        public IRequestRepository Requests { get; private set; }
        public ITimeSlotRepository TimeSlots { get; private set; }

        public void Complete()
        {
            _context.SaveChanges();
        }

        public async Task CompleteAsync()
        {
            await _context.SaveChangesAsync();
        }

        public void Dispose()
        {
            _context.Dispose();
        }
    }

Wszystko układało się chyba dobrze do momentu gdy zacząłem czytać o DI, z którym w pracy nie miałem styczności. Także nie wiem czy do każdej akcji w kontrolerze powinienem tworzyć osobny model i wywoływać jego nowy obiekt a wewnątrz dopiero za pomocą DI wstrzykiwać UoW? - może źle zrozumiałem poprzedniego posta.

Pozostało 580 znaków

2018-11-12 14:06
0

Controller zawiera Manager'a

Manager zawiera UnitOfWork

w controlerze wywolujesz

manager.FeatureA()

w managerze

public async Task FeatureA() 
{
  var repositoryA = this.unitOfWork.RepositoryA;

  var result = repositoryA,GimmeAll();

  await result.DoSomethingElse(); //  nie chcialo mi sie pisac logiki biznesowej, ale chyba powinno to wystarczyc jaki koncept
}

chociaz sam nie lubie slowa manager, mozesz uzyc slowa service czy co tam Ci sie podoba

DI robisz PerRequestScope i unitofwork jest wstrzykiwany w konstruktorze

edytowany 1x, ostatnio: fasadin, 2018-11-12 14:07

Pozostało 580 znaków

2018-11-12 14:33
Wielki Karp
0
fasadin napisał(a):

Controller zawiera Manager'a

Manager zawiera UnitOfWork

w controlerze wywolujesz

manager.FeatureA()

w managerze

public async Task FeatureA() 
{
  var repositoryA = this.unitOfWork.RepositoryA;

  var result = repositoryA,GimmeAll();

  await result.DoSomethingElse(); //  nie chcialo mi sie pisac logiki biznesowej, ale chyba powinno to wystarczyc jaki koncept
}

chociaz sam nie lubie slowa manager, mozesz uzyc slowa service czy co tam Ci sie podoba

DI robisz PerRequestScope i unitofwork jest wstrzykiwany w konstruktorze

Super! Świetne wytłumaczenie. Mam jeszcze jedno pytanie odnośnie dobrych praktyk w tym miejscu. Czy jeżeli akcja otrzymuje zbindowany ViewModel, np. z danymi użytkownika do rejestracji i chcę tymi danymi zasilić manager (serwis), czy lepszym podejściem jest tutaj przekazanie całego obiektu ViewModel do serwisu czy może robicie go na pojedyncze zmienne:


        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Register(RegisterViewModel model)
        {
            _userService.RegisterAsync(model.email, model.FistName, model.LastName, model.Password ...)
        }

W sumie to chodzi mi o to czy serwis powinien przyjmować ViewModele otrzymane z bindowania formularza czy powinien być bardziej uniwersalny.

Pozostało 580 znaków

2018-11-12 14:49
0

przekazuj caly viewModel zgodnie z zasada

YAGNI

Jezeli zauwazysz, ze ten sam feature bedzie uzywany dla roznych kontrolerow ale w sumie przyjmuja inne dane wtedy mozesz zastosowac wspolny obiekt, ale poki nie masz tego. Nie przejmuj sie tym

Pozostało 580 znaków

2018-11-12 15:03
1
_context = context;
Users = new UserRepository(_context);
Requests = new RequestRepository(_context);
TimeSlots = new TimeSlotRepository(_context);
A = new ARepository(_context);
B = new BRepository(_context);
C = new CRepository(_context);
D = new DRepository(_context);
E = new ERepository(_context);
F = new FRepository(_context);
(...)

Jakiż jest sens?

Pokaż pozostałe 3 komentarze
@WeiXiao: tak, pokazałeś to. Mi chodzi o to, ze autorowi, może sie nie wydawac to jako problem. Warto do problemu napisac jak go rozwiazac - fasadin 2018-11-12 17:57
@fasadin: Sam nie jestem pewien :P - WeiXiao 2018-11-12 18:09
Rozwiązanie tego problemu jest tutaj ---> Patterns of Enterprise Application Architecture. strona 169, Potem DDD Red book strona 469. :-| 69 to magiczna liczba. - ._. 2018-11-12 18:14
Usunąłem... - ._. 2018-11-12 18:15
Ewentualnie, możesz z tego "UOW' zrobić singletona, czy jakąś fabrykę abstakcyjną, która będzie tworzyć repo po typie. Jak dla mnie to daje poroniony pomysł. - ._. 2018-11-12 18:29

Pozostało 580 znaków

2018-11-13 03:25
0

Ale po co UoW ma być zależny od każdego repozytorium? Jak to się ma do Open/Closed Principle?


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."

Pozostało 580 znaków

2018-11-13 15:11
._.
0

Masz racje jest to zgodnie OCP, ale po co to w ogóle robić.?

Dla mnie to nie jest UOW. Ja to identyfikuje jako fabrykę Repository'iów z wrapem na sessje ORM, która pełni funkcje UOW oraz Data Mapper'a. Co jest dla mnie niezrozumiałe, ponieważ do tworzenia obiektów, które będą wstrzykiwane do serwisów jest Kontener.

UOW jest od śledzenia zmian w obiektach Domenowych/Persistence zależy jak to sobie zaimplementujesz. Ty jak pamiętam jesteś zwolennikiem oddzielania modelu Persistence'i. W teorii Repository nie musi nic wiedzieć o UOW.

Nie wydaje ci się dziwne, że w UOW znajdują się Rrepositories?

edytowany 2x, ostatnio: ._., 2018-11-13 15:38

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