MVC + camada 3; onde o ViewModels entra em ação?

11

Estou projetando um aplicativo de três camadas usando o ASP.NET MVC 4. Usei os seguintes recursos como referência.

Eu tenho o seguinte desenho até agora.

Presentation Layer (PL) (projeto principal do MVC, onde M do MVC foi movido para a camada de acesso a dados):

MyProjectName.Main
    Views/
    Controllers/
    ...

Camada lógica de negócios (BLL) :

MyProjectName.BLL
    ViewModels/
    ProjectServices/
    ...

Camada de acesso a dados (DAL) :

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

Agora, PL faz referência a BLL e BLL faz referência a DAL. Dessa forma, a camada inferior não depende da camada acima.

Nesse projeto, PL invoca um serviço da BLL. O PL pode passar um View Model para BLL e o BLL pode passar um View Model de volta para PL.

Além disso, o BLL chama a camada DAL e a camada DAL pode retornar um modelo de volta ao BLL. A BLL, por sua vez, pode criar um View Model e devolvê-lo ao PL.

Até agora, esse padrão estava funcionando para mim. No entanto, eu tive um problema em que alguns dos meus ViewModels exigem junções em várias entidades. Na abordagem simples do MVC, no controlador, usei uma consulta LINQ para fazer se joine depois select new MyViewModel(){ ... }. Mas agora, no DAL, não tenho acesso a onde os ViewModels estão definidos (no BLL).

Isso significa que não posso fazer junções no DAL e devolvê-lo ao BLL. Parece que eu tenho que fazer consultas separadas no DAL (em vez de junções em uma consulta) e o BLL usaria o resultado delas para criar um ViewModel. Isso é muito inconveniente, mas acho que não devo expor o DAL ao ViewModels.

Alguma idéia de como posso resolver esse dilema? Obrigado.

nômade
fonte

Respostas:

18

principal projeto MVC, onde M do MVC foi movido para a Camada de Acesso a Dados

Equívoco comum. O Mof MVCnão tem nada a ver com dados, apesar dos muitos exemplos e tutoriais que afirmam isso.

M é o seu ViewModel e deve residir no seu projeto MVC. Os ViewModels que você possui na sua BLL devem ser chamados DataContracts ou BusinessModels.

No seu controlador, você tem algo comparável a isso:

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

Em seu serviço, algo como isto:

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

E no DataAccess, você realiza as junções apropriadas de acordo com o objeto solicitado. No entanto, é claro que você pode adicionar métodos personalizados ao seu DataAccess quando necessário, para que seu serviço possa chamar esses métodos:

GetWithBars():
    dataModels = _repository.Query("select from foos join bars");
    return dataModels;
CodeCaster
fonte