Poziom MVC + 3; gdzie wchodzi ViewModels?

11

Projektuję 3-warstwową aplikację przy użyciu ASP.NET MVC 4. Użyłem następujących zasobów jako odniesienia.

Do tej pory mam następujący desingn.

Warstwa prezentacji (PL) (główny projekt MVC, gdzie M z MVC została przeniesiona do Data Access Layer):

MyProjectName.Main
    Views/
    Controllers/
    ...

Warstwa logiki biznesowej (BLL) :

MyProjectName.BLL
    ViewModels/
    ProjectServices/
    ...

Warstwa dostępu do danych (DAL) :

MyProjectName.DAL
    Models/
    Repositories.EF/
    Repositories.Dapper/
    ...

Teraz PL odwołuje się do BLL, a BLL do DAL. W ten sposób dolna warstwa nie zależy od tej nad nią.

W tym projekcie PL wywołuje usługę BLL. PL może przekazać View Model do BLL, a BLL może przekazać View Model z powrotem do PL.

Ponadto BLL wywołuje warstwę DAL, a warstwa DAL może przywrócić model z powrotem do BLL. BLL może z kolei zbudować model widoku i zwrócić go do PL.

Do tej pory ten wzór działał dla mnie. Jednak natknąłem się na problem polegający na tym, że niektóre z moich modeli ViewModels wymagają łączenia na kilku obiektach. W zwykłym podejściu MVC, w kontrolerze użyłem zapytania LINQ, aby wykonać joins, a następnie select new MyViewModel(){ ... }. Ale teraz w DAL nie mam dostępu do tego, gdzie są zdefiniowane ViewModels (w BLL).

Oznacza to, że nie mogę wykonać połączeń w DAL i zwrócić go do BLL. Wydaje się, że muszę wykonać osobne zapytania w DAL (zamiast łączyć w jednym zapytaniu), a BLL użyje ich wyniku do zbudowania ViewModel. Jest to bardzo niewygodne, ale nie sądzę, że powinienem wystawiać DAL na ViewModels.

Jakieś pomysły, jak rozwiązać ten dylemat? Dzięki.

koczownik
źródło

Odpowiedzi:

18

główny projekt MVC, w którym M MVC zostało przeniesione do warstwy dostępu do danych

Powszechne niezrozumienie. MZ MVCnie ma nic wspólnego z danymi, mimo wielu przykładów i ćwiczeń, które twierdzą tak.

M jest twoim ViewModel i powinien znajdować się w twoim projekcie MVC. Modele ViewModels, które masz w BLL, mają faktycznie nosić nazwę DataContracts lub BusinessModels.

W twoim kontrolerze masz coś porównywalnego do tego:

Get(id):
    dataContract = _service.Get(id);
    viewModel = Map(dataContract);
    return viewModel

W twoim serwisie coś takiego:

Get(id):
    dataModel = _dataAccess.Get(id);
    dataContract = Map(dataModel);
    return dataContract;

A w DataAccess wykonujesz odpowiednie połączenia zgodnie z żądanym obiektem. Oczywiście możesz jednak dowolnie dodawać niestandardowe metody do DataAccess, aby usługa mogła wywołać te metody:

GetWithBars():
    dataModels = _repository.Query("select from foos join bars");
    return dataModels;
CodeCaster
źródło