How to deal with MVC ViewModel - Domain Model - Entity in MVC controllers and services

1.2k views Asked by At

We are writing a MVC data maintenance application is part of a larger project. We try to use domain-driven design DDD. There are already other questions about this on SO, like here, here and here. Yet they don't fully answer my question.

We also have bounded contexts in the data layer, since the database has 755 tables. So we created bounded contexts for business, roles, products, customers, etc.

The problem we have is that in the MVC application we have a view for "intial setup" which uses a ViewModel that in the end spans multiple bounded contexts (using IUnitOfWork pattern in Entity Framework 6). That view must therefore write to the business context, and roles context.

The domain model would have a Business model and an Address model and a few other models in a larger pbject graph.

The ViewModel is a flattened, simplified model of these two and other domain models:

public class InitialSetupViewModel
{
    string BusinessName{get;set;}
    string Street{get;set;}
    string Street2{get;set;}
    string State{get;set;}
    string ZIP{get;set;}
    ...
}

This ViewModel should map to the domain models, which we are doing with Automapper.

The controller gets the domain service injected:

public class SetupController : Controller
{
    private readonly IMaintenanceService service;

    public SetupController( IMaintenanceService maintenanceService = null )
     {
        service = maintenanceService;
    }

    public void Create(...????....)
    {
        service.CreateBusiness(..?.);
    }

}

Problems:

  1. The service can't know about the InitialSetupViewModel, so what should be passed to the service?

  2. The service must know about the BusinessDbContext and RolesDbContext. So I must call SaveChanges() on both, which beats the purpose of having a single IUnitOfWork. Do I have to create yet another UnitOfWork that includes both business and roles entities?

I don't think it's justifiable to combine these two IUnitOfWorks into one just to make this MVC view work. But what is the solution?

Thank you!

1

There are 1 answers

0
Oskar Lindberg On BEST ANSWER

It's always hard to have a strong opinion about a domain you don't know, but here it goes:

  1. As has been commented already, the Controller should assume responsibility for mapping between view and domain models, DTOs or what have you. It could take an instance of InitialSetupViewModel as input, but implementation details may vary.

  2. It is true that remodeling the domain may be the correct choice if you find yourself in need of otherwise breaking the borders of your bounded contexts. Focusing just on the Unit of Work pattern though, I don't quite get your hesitation.

    It is the responsibility of a Unit of Work implementation to keep track of all the domain objects that need to be in sync within one transaction. There is nothing odd about the same domain object(s) being involved in several different Units of Work. This does not mean that you should combine "smaller" Unit of Work implementations into "larger" ones when you're dealing with another type of aggregate, but including both "roles" and "businesses" in one Unit of Work, sure.

    Doing this should not be enticed by what your view looks like, but by what is "true" in your domain model(s), and rather than dealing just with collections of domain objects, your domain should probably describe suitable aggregates.

Maybe it's even OK to store each domain object with separate transactions (Units of Work), i.e. if synchronizing them is not necessary -- e.g. it's still fine if (or perhaps even desired that) failing to persist Business does not stop Roles from getting through or vice versa. Actually, I think one could even argue that if the bounded contexts are in fact correctly defined, this should be the case.

I hope these comments help.

Martin Fowler on Unit of Work and Aggregates.