1

Given an MVC3 app using the ViewModel pattern and the Repository pattern with Entity Framework.

If I have a create and update view each composed of multiple entities,  what is the best practice for saving the data?

Should I save the date using an abstracted service layer which will save the data for each entity with its respective repository or should I save the data in the repository using a stored procedure?

I'm open to any suggestions or recommendations.

Thanks in advance!

Rich
  • 1,895
  • 3
  • 26
  • 35
  • It really depends on how the entities are related. Do the values of one entity depend on another? Are the entities really just one big entity split up into smaller manageable bits? – Garvin Apr 25 '12 at 23:21
  • @Garvin its really just one big entity with eager loaded related entities. For example, I would eager load details for a widget and then have to edit one of the details. Since my context gets disposed after I retrieve the data, I believe I would have to attach each related entity and then save. I would have to do this in the Save method of the repo for the main object so saving all the related objects is somewhat misleading. Thoughts? – Rich Apr 26 '12 at 01:16

1 Answers1

1

This is one of those cases where a DDD/CQRS approach makes most sense. Simply put, you have some business objects which models a specific behavior (an aggregate). There is one object in chrage called the Aggregate Root (AR) which has explicit boundaries. When you want to save it, you send the whole AR to the repository which then saves everything as a transaction.

The workflow

User sends the data via a view model. The controller will then retrieve the AR from the repository or creates if it's new . THe input data is mapped to the AR, usually via an AR method. IF the AR finds that the data or the result of it, breaks some business rules then it should throw an exception (we assume that basic validation was already performed automatically by asp.net mvc).

If everything is ok, the controller will send the AR to the repo which then it will proceed to map the AR to EF entities and then saves it, all within a transaction.

THis is in a nutshell how I'd do it. Of course, I'd actually implement it a bit different, but the concepts are the same. THe important part is to send all the data to the AR which will know how to handle relationships.

Important points

Note that I've mentioned EF only after the AR got to the repo. This means, the AR has no relation to EF entities is completely separated and serves the actually business model. Only after the model is updated, we care about EF and ONLY within the repo (because EF is an implementation detail of the repo). The repo only transfers (maps basically) AR data to the relevant EF entities and then saves the entities.

It's important to have a very clear distinction between the business (domain) model and the persistence modewl (EF entities). Don't use EF to handle business rules, use it only to stare/retrieve data from db. EF was made to abstract RDBMS access only, use it as a virtual OOP database.

You've mentioned the ViewModel pattern. I haven't heard about such a pattern, everytime you're using MVC you're already using ViewModels. One again, the trick is NOT to use EF entities as ViewModels. Use 'dumb' view models fitted for the views. Populate the VM via a specialized Queries repository which will return directly VM parts. The repo will query EF entities and then return those VM bits which are simple DTO's. That's because you don't need validation and business rules when showing data.

I think it is a good practice to keep the layers and especially each layer's model separated. For updating stuff, use complex business objects(domain model) which will do the hard work and then only transfer their state to EF (via repository). For reading stuff, query EF and return simple DTOs fit for VM.

This is what CQRS is really about: don't try to fit different responsibilities (write and read) in a single model.

MikeSW
  • 16,140
  • 3
  • 39
  • 53
  • This is kinda what I had in mind, difference being parsing out the AR in an abstracted service layer to avoid doing that in the controller or repository; implementation differences mainly with your recommendation. So....would taking the AR and passing it to a sproc for inserts and updates from the controller to the repo be cleaner? – Rich Apr 26 '12 at 13:20
  • You don't parse the AR. You map the input data to the AR via a command (from controller or a service) then you send the AR to the repo and inside the repo, you map the AR to EF entities. sproc or not it doesn't matter. What matters is to keep the layers separated. That's how you keep them clean. – MikeSW Apr 26 '12 at 13:32
  • Right. That's what I meant by parse. Thanks for the post! – Rich Apr 26 '12 at 14:04