Hi,
I have looked at plenty of examples of harnessing entity framework using MVVM pattern, with a single client. In a typical approach I have seen, EF entities are used as the model layer for the MVVM application. These entities are wrapped in a viewmodel.
- In a typical data editing scenario, let's say the user is editing a collection of customers in a data grid. The EF customer entities are loaded from the database when first opening the view, and wrapped in viewmodels.
- The changes the user makes to customer entitie(s) in the data grid. The model entities that are changed during this process are tracked using the EF data context.
- When the user goes to save their changes, the changed entities are sent to the database using EF's tracking of which loaded entities have actually changed.
- Whether the save was successful or not, post attempt to save, the latest data is then retrieved again from the database and the view refreshed with the latest updated data.
Do let me know if any of the above is incorrect or against typical/best practices?
I want to enhance the scenario above to decouple from EF using an abstract data service, and also elegantly handle multiple clients editing these records at the same time.
- I want to elegantly handle conflicts with multiple clients editing the same records at the same time.
- And, I don't want to tie myself to querying and saving data using only EF. I want to potentially connect to other data services (such as a message router service that I can send commands to fetch or save my model entities). That means my model entities cannot be EF entities (with their particular plumbing) but must probably be POCOs.
I've tried to find some solid examples of the above scenario online, and in books, but I've found this difficult, and so I've tried to come up with the following approach - I'll continue with the data grid of customers scenario above:
- Model entities are just POCOs. They contain no property changed notification, or any ties to a particular data access layer. All however must have a unique ID, a modified date/time when they were first loaded, and a last modified date/time.
- The actual data access layer bit is abstracted out into a service implementation, for each entity I create. For example for customers I could have:
public interface ICustomerService { // Queries IEnumerable<Customer> GetAllCustomers(); IEnumerable<Customer> FindCustomersWithSurname(string surname); // Saving void Save(IEnumerable<Customer> entities); }
Now this is feeling a bit more like DDD, in that my model entities are quite dumb and don't care about the data access implementation.
- Viewmodel does have property changed notifications. The wrapped model last modified date/time is updated when the viewmodel detects a change (via the view).
- When the customers collection is first loaded, I call CustomerService.GetAllCustomers(). It is wrapped in my viewmodels. The list of customers after first being loaded isonly refreshed from the data service if the user manually hits a refresh button, or post attempt to save any changes.
- When the user goes the save, in the viewmodel I check for any customer model entities where the initial modify date/time is not equal to the last modify date/time. These are may changed entities. I send these to the data service for saving using the CustomerService.Save(<changedcustomers>) call.
- On saving, if any customer's last modified date/time in the database is not equal to that now in the data record, I throw a conflict error as someone else has edited the same records since they were last refreshed. If not, I save.
- I then immediately reload all customers again to get the latest picture of the customers - which may have been changed by other clients since it was last refreshed.
Does that sound like best practice for this scenario? Does anyone have any experience they could share of using this sort of architecture?
Thank you