MVC + 3 niveles; ¿Dónde entran en juego los ViewModels?

11

Estoy diseñando una aplicación de 3 niveles usando ASP.NET MVC 4. Usé los siguientes recursos como referencia.

Tengo el siguiente diseño hasta ahora.

Presentation Layer (PL) (proyecto MVC principal, donde M de MVC se movió a Data Access Layer):

MyProjectName.Main
    Views/
    Controllers/
    ...

Capa de lógica de negocios (BLL) :

MyProjectName.BLL
    ViewModels/
    ProjectServices/
    ...

Capa de acceso a datos (DAL) :

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

Ahora, PL hace referencia a BLL y BLL hace referencia a DAL. De esta manera, la capa inferior no depende de la capa superior.

En este diseño, PL invoca un servicio de BLL. PL puede pasar un modelo de vista a BLL y BLL puede pasar un modelo de vista a PL.

Además, BLL invoca la capa DAL y la capa DAL puede devolver un modelo a BLL. BLL a su vez puede construir un Modelo de Vista y devolverlo a PL.

Hasta ahora, este patrón funcionaba para mí. Sin embargo, me he encontrado con un problema en el que algunos de mis ViewModels requieren uniones en varias entidades. En el enfoque simple de MVC, en el controlador utilicé una consulta LINQ para hacer joinsy luego select new MyViewModel(){ ... }. Pero ahora, en el DAL no tengo acceso a donde se definen los ViewModels (en el BLL).

Esto significa que no puedo hacer uniones en DAL y devolverlo a BLL. Parece que tengo que hacer consultas separadas en DAL (en lugar de unir en una consulta) y BLL usaría el resultado de estas para construir un ViewModel. Esto es muy inconveniente, pero no creo que deba exponer DAL a ViewModels.

¿Alguna idea de cómo puedo resolver este dilema? Gracias.

nómada
fuente

Respuestas:

18

proyecto MVC principal, donde M de MVC se trasladó a la capa de acceso a datos

Malentendido común. El Mde MVCno tiene nada que ver con los datos, a pesar de los muchos ejemplos y tutoriales que lo afirman.

M es su ViewModel y debe residir en su proyecto MVC. Los ViewModels que tiene en su BLL en realidad se denominarán DataContracts o BusinessModels.

En su controlador tiene algo comparable a esto:

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

A su servicio, algo como esto:

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

Y en DataAccess, realiza las uniones adecuadas de acuerdo con el objeto solicitado. Sin embargo, por supuesto, puede agregar métodos personalizados a su DataAccess cuando sea necesario, por lo que su servicio puede llamar a esos métodos:

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