views:

248

answers:

4

We've written a web service which uses a simple entity translator to map the values of DTO back on to "real" server side business objects. As part of this excercise. We have come across an "interesting" distinction between explicitly set null values and clients having not set a value.

The problem is essentially that we want to set a default value on the real business object if the client has not explicitly set a value, however using standard nullable types there is no way to tell if a client has explicitly meant "set this to null" or just not set it.

The solution here is obviously some sort of "flag".

Within a business object we can track the state of a field internally using private "IsDirty" flags set within the property setters, but a DTO only really specifies an Interface so this means exposing this data to the public. This leaves a number of implementation options. The language is C# (so statically typed) so...

1) We could expose an "IsSet" flag on each property? 2) We could expose each property as a class which has a .Value and .IsSet property? etc. etc.

How would you choose to expose these "flags" on the Data Contract? What would you here regard as best practice for this?

Any opinions on this would be greatly appreciated.

+2  A: 

Using a class for each property value would be more scalable that having to declare a bool for each property. It would also enable you to chose which properties are able to be left empty and/or set to null.

Stevo3000
+1  A: 

You could write a class that wraps the flags with the data:

public class DtoData<T> 
{
  T data;
  bool IsSet { get; private set; }
  T Data 
  { 
    get { return data; }
    set { data = value; IsSet = true; } 
  }
}


public class XyzDto 
{
  // only private setters, initialize in constructor
  DtoData<int?> SomeInt { get; private set; }
  DtoData<string> SomeString { get; private set; }
}

This has some disadvantages so. For instance, that all your data is wrapped in a reference type, so the reference to DtoData could still be null, you need to create them in a constructor. And it's hard to make values accessible only internal or protected.


Personally, I would try to avoid this problem. Why should "not defined" actually exist? Are you sending around differences, incomplete Dtos, or where does it come from? This problem could come with filters, where you need a difference if you filter a field for null or if you don't filter it at all. But for such scenarios, you need a special "field-filter" class anyway.

Stefan Steinegger
A: 

I have come across this exact problem before. You could work around this by introducing a some default value on construction of the DTO, but is is not ideal. I have blogged in more detail here, it might help someone understand the issue further.

Nic Strong
+1  A: 

In general, what you're talking about here is a default value which is different from any value which the user can set. So just specify that; set the default to a value which is not in the allowable range of values the user can set. That way, if the value is the default, you know it hasn't been set; if the value is anything other than that, you know the user has tinkered with it. Just because one of the user-settable values is null seems to be throwing you off; just consider it to be one of the set of user settable values; make the entire range of the variable a slightly larger set, with one additional default value. That should solve your problem.

McWafflestix