I'm trying to piece together an architecture for a Windows Universal App leveraging Azure Mobile Services. It's a LOB app and will need to handle 100-250 offline\online tables. Currently Mobile Services doesn't support nested complex objects so on the service side I've mapped most of my tables straight through from entity framework.
The question I have is whether I should use a separate layer to reconstitute the DTO's or if i should be doing this all through the service layer and the view model. My main concerns are isolation of responsibility (large team) and the performance overhead from the additional mapping.
Didn't have the reputation to add an image here's the link to the model.
An example would be a Person object with a collection of addresses attached. I have three DTO objects: one for the person one for the address and one for the many to many relationship. If I'm mapping straight through to the view model i'd need an addressing service to lookup the address for a specific person.
If i insert an extra "Model" layer my service returns the Person Model with a Collection of address on it. It feels a bit wrong though...
The right choice depends on how you are doing querying on the client. In your case, you want to do querying on Address directly, so it is probably helpful to have an Address table on the client.
The reason for doing the mapping to DTOs is exactly as you said: there is no direct support for relationships between objects in Azure Mobile Services. This is by design to ensure a simple model for interacting between client and server, but it can mean more design when the data model does involve relationships.
In general, we advise the following:
If you have 1:many relationships where there is an explicit ownership relationship between parent and children, it is usually best to map the child objects into the parent. This also simplifies the case when the mobile client creates new child objects and associates with the parent. The offline sync protocol sends changes individually, so objects must be grouped together if they need to be one atomic action. For an example of this, see the FieldEngineerLite sample.
If you have 1:many relationships and it's not important to query on the child objects directly, you can either map as in #1, or create separate table controllers for the children and manage the mapping with foreign keys.
For many:many relationships, it usually adds too much complexity to expose the relationship table directly. Here, consider flattening the object IDs into one of the objects. In your example, the Customer DTO could have a list of Address IDs, and the addresses are in their own table on the client.
If you choose to do option #3, your code needs to make sure that all the relevant addresses are sent down to the client. You could either a) map to a flattened object and then unpack on the client side, or b) add clauses to either the client or server side query for addresses so that the client gets all the right data.
In case (b), you should also ensure that changes to the Address table are pulled down before doing queries on the Customer table. Case (b) is easy to implement if there is a query that can be done to scope what addresses to pull down.
For instance, suppose you are building a CRM app where a customer is assigned to the salesperson using the app. Then, you do a join on Customer and Address and get only those Addresses that belong to a customer owned by the logged in user.