1

I want to save edited values from a WPF mobile app, via a Web API, as the user tabs out of each field. So on the LostFocus event.

When using EF then the whole entity graph is posted (put) to the Web API each time a field is updated. Even if I just make a DTO for the basic fields on the form, I would still be posting unnecessary data each time.

I was thinking of forgetting about EF in the Web API and simply posting the entity ID, field name and new value. Then in the controller, create my own SQL update statement and use good old ADO.Net to update the database.

This sounds like going back to the noughties or even the nineties, but is there any reason why I should not do that?

I have read this post which makes me lean towards my proposed solution.

Thanks for any comments or advice

Community
  • 1
  • 1
Graeme
  • 2,597
  • 8
  • 37
  • 50
  • Just because your entity contains a lot of properties, doesn't mean your DTO also has to. You could have specific DTOs that have a limited amount of properties. E.g. for a `Student` entity, you could have a `StudentListItem` DTO that only contains the `FirstName` and `LastName` properties if they are the only properties used when showing a list of students. – Flater Apr 28 '15 at 07:54
  • *When using EF then the whole entity graph is posted (put) to the Web API each time a field is updated* What do you mean with this? Only the updated field is sent. – Loetn Apr 28 '15 at 07:56
  • @Loetn: If the client uses the same entity as the WebAPI, and I edit a student which has a collection of courses, then the whole student entity with the courses collection is passed back to the API controller. – Graeme Apr 28 '15 at 08:57
  • @Flater: sure, but my edit form maybe has 20 fields, so that is still 19 unnecessary fields going back to the server 20 times if I update all fields. – Graeme Apr 28 '15 at 08:58
  • @Graeme: As a first idea, you could just send the *changed* fields, and leave the rest as `null`. Is your primary concern for the security of said data, bandwidth used, efficient coding principles, ...? – Flater Apr 28 '15 at 09:24
  • You can individually update fields so that only those are sent to the database. Do you really have that many updates that it warrants such worries though? – Jeroen Vannevel Apr 28 '15 at 09:36
  • @Flater: If I leave fields as null, how can I tell they have not been updated to null (the client has no EF dbContext, only the service)? Mostly looking at bandwidth and efficient coding. – Graeme Apr 28 '15 at 11:24
  • @Jeroen - I won't have a save button - update is done after editing every individual field, so I just want to reduce the wire traffic and hopefully increase the speed. – Graeme Apr 28 '15 at 11:26

1 Answers1

3

Sounds like you are trying to move away from having a RESTful Web API and towards something a little more RPC-ish. Which is fine, as long as you are happy that the extra hassle of implementing this is worth it in terms of bandwith saved.

In terms of tech level, you're not regressing by doing what you proposed; I use EF every day but I still often need to use plain old ADO.NET every now and then and there is a reason why it's still well supported in the CLR. So there is no reason not to, as long as you are comfortable with writing SQL, etc.

However, I'd advise against your current proposal for a couple of reasons

Bandwidth isn't necessarily all that precious

Even for mobile devices, sending 20 or 30 fields back at a time probably isn't a lot of data. Of course, only you can know for your specific scenario if that's too much but considering the wide-spread availability of 3 & 4G networks, I wouldn't see this as a concern unless those fields contain huge amounts of data - of course, it's your use case so you know best :)

Concurrency

Unless the form is actually a representation of several discrete objects which can be updated independently, then by sending back individual changes every time you update a field, you run the risk of ending up with invalid state on the device.

Consider for example if User A and User B are both looking at the same object on their devices. This object has 3 fields A, B, C thus:

A-"FOO"
B-"42"
C-"12345"

Now suppose User A changes field "A" to "BAR" and tabs out of the field, and then User B changes field "C" to "67890" and tabs.

Your back-end now has this state for the object:

A - "BAR"
B - "42"
C - "67890"

However, User A and User B now both have an incorrect state for the Object!

It gets worse if you also have a facility to re-send the entire object from either client because if User A re-sends the entire form (for whatever reason) User B's changes will be lost without any warning!

Typically this is why the RESTful mechanism of exchanging full state works so well; you send the entire object back to the server, and get to decide based on that full state, if it should override the latest version, or return an error, or return some state that prompts the user to manually merge changes, etc.

In other words, it allows you to handle conflicts meaningfully. Entity Framework for example will give you concurrency checking for free just by including a specially typed column; you can handle a Concurreny exception to decide what to do.

Now, if it's the case that the form is comprised of several distinct entities that can be independently updated, you have more of a task-based scenario so you can model your solution accordingly - by all means send a single Model to the client representing all the properties of all of the individual entities on the form, but have separate POST back models, and a handler for each.

For example, if the form shows Customer Master data and their corresponding Address record, you can send the client a single model to populate the form, but only send the Customer Master model when a Customer Master field changes, and only the Address model when an address field changes, etc. This way you can have your cake and eat it because you have a smaller POST payload and you can manage concurrency.

Community
  • 1
  • 1
Stephen Byrne
  • 7,400
  • 1
  • 31
  • 51
  • Yes, I need to read up on EF & concurrency. Am I right in thinking if I use a DTO as Flater suggests above, I still need to convert it back to the entity model, set only the required fields to modified, then save, and deal with any concurrency issues EF notices? – Graeme Apr 28 '15 at 14:58
  • @Grame, yes that is correct, typically the process I would use is 1. Receive the DTO 2. Grab the entity from the EF Data Context based on for e.g an ID property on the DTO. 3. Set properties from the DTO to the entity 4. Ask the EF Data Context to `SaveChanges()` and catch any `OptimisticConcurrencyException` that's thrown and then decide how to proceed. There is a very good article [here](http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/handling-concurrency-with-the-entity-framework-in-an-asp-net-mvc-application) that explains it better than I do :) – Stephen Byrne Apr 28 '15 at 15:04
  • I have a follow up question on this: in step 2 I don't want to read the whole entity with its navigation properties and all fields from the database as my DTO has only a subset of them. Yet I don't know how to have 2 unrelated entities pointing to the same table. I've seen examples of "Table splitting" where two entities have different properties but come from the same table. In my case one entity will have some of the same properties as the other, just fewer of them. Any tips here? – Graeme May 06 '15 at 15:22
  • @Graeme, you could check out [Automapper](https://github.com/AutoMapper/AutoMapper/wiki) and specifically the "Projections" feature which will allow projection at the database level (i.e only select those fields you include in the `Select()` projection target). I think this could help you - unless I misunderstood...perhaps this warrants its own question? – Stephen Byrne May 06 '15 at 15:28