11

I'm designing a 3-tiered application using ASP.NET MVC 4. I used the following resources as a reference.

I have the following desingn so far.

Presentation Layer (PL) (main MVC project, where M of MVC was moved to Data Access Layer):

MyProjectName.Main
    Views/
    Controllers/
    ...

Business Logic Layer (BLL):

MyProjectName.BLL
    ViewModels/
    ProjectServices/
    ...

Data Access Layer (DAL):

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

Now, PL references BLL and BLL references DAL. This way lower layer does not depend on the one above it.

In this design PL invokes a service of the BLL. PL can pass a View Model to BLL and BLL can pass a View Model back to PL.

Also, BLL invokes DAL layer and DAL layer can return a Model back to BLL. BLL can in turn build a View Model and return it to PL.

Up to now this pattern was working for me. However, I've ran into a problem where some of my ViewModels require joins on several entities. In the plain MVC approach, in the controller I used a LINQ query to do joins and then select new MyViewModel(){ ... }. But now, in the DAL I do not have access to where ViewModels are defined (in the BLL).

This means I cannot do joins in DAL and return it to BLL. It seems I have to do separate queries in DAL (instead of joins in one query) and BLL would then use the result of these to build a ViewModel. This is very inconvenient, but I don't think I should be exposing DAL to ViewModels.

Any ideas how I can solve this dilemma? Thanks.

2 Answers 2

18

main MVC project, where M of MVC was moved to Data Access Layer

Common misconception. The M of MVC has nothing to do with data, despite the many examples and tutorials that claim so.

M is your ViewModel and should reside in your MVC project. The ViewModels you have in your BLL are actually to be named DataContracts or BusinessModels.

In your controller you have something comparable to this:

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

In your service, something like this:

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

And in the DataAccess, you perform the proper joins according to the object requested. You are however of course free to add custom methods to your DataAccess when required, so your service can call those methods:

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

To get best practice of three-tier architecture:

Their should be another helping layer known as Business Entity Layer (BEL) and all the remaining layer should reference it and each class can access it. Models should be placed here. Whereas in BLL you should perform logical operations.

  1. Presentation Layer (References of BLL and BEL)
  2. Business Logic Layer (References of DAL and BEL)
  3. Data Access Layer (Reference of BEL)
  4. Business Entity Layer (It will have No References)
1
  • Whereas ViewModels will be in PAL Project. Oct 15, 2021 at 12:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.