views:

87

answers:

6

I'm developing an application that does some CRUD operations through a WCF service. The read method returns a complete entity, the update is performed through a legacy system, and only the changed values should be updated.

What is the best way to design the data contract for this scenario without simply sending a dictionary of key-value pairs?

+1  A: 

The only other thing I can think of is to make your component durable - i.e. persist its state to a file or database. That way, on the update you can compare the previous state to the state being passed in. I'm not sure that's a good way to go since it will introduce more overhead than just passing in the key-value pairs.

From the outside it might look more CRUDy or whatever, but from a practical standpoint you may be better off just passing some indication as to which values changed.

Terry Donaghe
A: 

the best way to do this is with property dictionary, just represent your entities as dictionary of property name and value. save all changes in some list and pass a partial dictionary with all changed properties.

i think this is best design,

if u wanna avoid this design, send entire entity with some list of changed properties. (to save transport u can put null on other properties)

if u don't wanna change the service contract signature u can push the names of modified properties on the header

Chen Kinnrot
I wanted to avoid a dictionary of key-value pairs for two reasons;1. The client doesn't know what properties are available and valid for a given entity. I want this to be explicit in the contract. If the names of properties are changed later, I want this to be a breaking change of the contract. Also, only selected properties of the entity can be changed, so there must be an easy way for the user to know this.2. I want the contract to be strongly typed, as some properties are string, DateTime, int, Enums etc. Can this be achieved with a dictionary?
Andronicus
make a wrapper dto for the transport layer, somthing that will wrap each property in a strongly typed way, and tells you every thing u need to know about it; changed, selected...i recommand you to use some kind of code generating tool to maintain this dto's
Chen Kinnrot
A: 

I had two ideas of how to achieve this;

  1. Have the client send both the original entity, and the changed entity in full, the service would then figure out what properties were changed.

  2. Use a pattern similar to Nullable, lets call it Modified with an IsModified flag and a NewValue property of type T. Each property of the DataContract would be of this type, the service can check the IsModified flag when performing the update.

The legacy sytem we use has an api that accepts String.Empty to identify unmodified fields, a '?' character is used to indicate an update to an empty string. I really don't like this, the user of the api is forced to read the documentation, and if you actually want to store a '?' you can't. I want our webservice api to be more explicit.

Andronicus
A: 

You can use DataSet to keep your changes. Call your record as DataSet then assign some values to the record. DataSet.Tables[0].GetChanges() will give you the columns which were changed.

HamdiKavak
A: 

You could leave the data contract alone and update your service contract. Just represent the required fields for the method as properties within the service contract. Any consuming application using the service will have to be updated if the service contact changes, but the consuming application will know what is required to successfully update the data.

There are positives and negatives to this method, but I use it when a method I am writing doesn't require the full data contract.

--Edited for a spelling error--

Edison
I'm not sure I understand. lets say our entity has 10 properties. The client could choose to update 1,2.... or all properties. So how does the service identify what properties are not updated from those that are updated to Null?
Andronicus
The OperationContract would define the required parameters. Effectively you would have multiple methods (possibly with similar names) requiring different parameters. This would be similar to an overloaded method, but you would have to use the[OperationContract(Name = "{UniqueName}")] attribute on the service contract.
Edison
but I would need hundreds of such methods, the entity can have 20-30 fields, and the user can update any of these.Are you saying that each permutation would need its own service operation overload?
Andronicus
If you have to support every permutation this may not be the best solution. When I have worked with legacy systems in the past, I find only those permutations that are required by the legacy app and it greatly limits the number of methods I need to write. I don't think there is any perfect solution for what you are describing.
Edison
A: 

Looking at your requirements and statements, i've made a few assumptions before starting to write my vision on a possible solution:

  • You are using the same class for retrieving (return value type of "read" operation) and updating an item (input parameter type of "update" operation) in your WCF service.
  • Your current problem of implementation is how to use the original class (not a dictionary) AND still be able to determine 'what has changed compared to the read' when you get the "Update" operation called on your WCF service
  • You are writing both the server and client. Both are written using the MS .Net framework.

If this is true, the problem lies in the Update method missing information. The information required is 'has changed' which could be inferred if a 2nd state is present to compare against or should already be present along side the state to update in the back-end.

Since you only have the 'back-end state' (without flags) when the client posts its data to the WCF service, how should we determine what did change? Obviously, we want to prevent another 'read' roundtrip to get the current server state and start comparing.

Sending the original & changed state from the client to the server is a possible but heavy solution. Next to that, the client isn't interrested in this information, the server is.

Adding this all up makes my guess is that changing the type of the 'Update' operation input parameter is the easiest way to go. Create a decorator class that adds 'dirty bit' behavior to the original entity. Use this new class as input parameter for your "Update" operation. You then will have the availability in the server to check this dirty bit next to the full state send by the client. The major change on the client side is that the object needed for the 'Update' operation is no longer the same as the one provided by the 'Read' method. To eleviate this pain, i would probably create a decorator class which added the required 'dirty bit' handling. This only requires the object instanciation to change, while maintaining the interface signature for the client (very little code changes).

Marvin Smit
I think this is the way to go, but the 'dirty bit' needs to indicate each individual property that has changed, we need that 'has changed' information on every property.I've implemented this with a ChangedProperty<T> class, so although the read and update data contracts have the same property names, the types of each property are different, but we can distinguish between a new Null value, and an unchanged value...myProperty == null //indicates not changedmyProperty.value == null //indicates changed to nullmyProperty.value != null //indicates a new value
Andronicus