0

I have a WCF service that allows external application to update my database. I have an Update Operation Contract that accepts a Data Contract that the external application should set. My problem is that I cannot distinguish what was set to null and what was not actually set because when the data contract is serialized the value is always null. Consider the following data contract:

[DataContract, XmlRoot("Person")]
public class Person: BaseEntity
{
    [DataMember, XmlElement]
    public string Prefix { get; set; }
    [DataMember, XmlElement]
    public string FirstName { get; set; }
    [DataMember, XmlElement]
    public string MiddleName { get; set; }
    [DataMember, XmlElement]
    public string LastName { get; set; }
    [DataMember, XmlElement]
    public string MaidenName { get; set; }
    [DataMember, XmlElement]
}

One external application can only set the FirstName and the LastName and ignore the rest of the properties. But when my WCF service receive the request, the other properties are set to null. So my update statememt in my WCF service would think those properties where set to null. I wish to find a way to determine the properties were not set so that my update statement could ignore those properties.

  • Please also consult [this related post](http://stackoverflow.com/questions/774192/what-is-the-correct-way-to-represent-null-xml-elements) – Adam Caviness Apr 08 '14 at 16:28
  • Adam, unfortunately I don't intend to parse the xml manually and rely on XML seriialization. And an XML element that is not set or set to null will always be deserialized the same, which is null – CzarEclarinal Apr 08 '14 at 23:16

2 Answers2

0

You can not distinguish the two cases. Every variable starts their life time with an initial value, null for reference types, 0 for integers and floating point numbers and so on. In consequence there is absolutely no difference between

String firstName;

and

String firstName;

firstName = null;

This means that you have to perform the tracking manually if you need this information.

String firstName;
Boolean firstNameSet;

firstName = null;
firstNameSet = true;

Note that with manually I mean you have to keep track of that information manually, you can of course add some tracking code to your property setters so that users of your class don't have to be aware of this.

public class Person
{
   private String firstName = null;

   private Boolean firstNameSet = false;

   private String lastName = null;

   private Boolean lastNameSet = false;

   public String FirstName
   {
      get { return this.firstName; }
      set
      {
         this.firstName = value;
         this.firstNameSet = true;
      }
   }

   public String LastName
   {
      get { return this.lastName; }
      set
      {
         this.lastName = value;
         this.lastNameSet = true;
      }
   }
}

There are a lot of other alternatives to implement this, for example you can use a set to track set properties. The best solution obviously depends on your requirements.

public class Person
{
   private readonly ISet<String> setProperties = new HashSet<String>();

   private String firstName = null;

   private String lastName = null;

   public String FirstName
   {
      get { return this.firstName; }
      set
      {
         this.firstName = value;
         this.setProperties.Add("FirstName");
      }
   }

   public String LastName
   {
      get { return this.lastName; }
      set
      {
         this.lastName= value;
         this.setProperties.Add("LastName");
      }
   }
}
Daniel Brückner
  • 59,031
  • 16
  • 99
  • 143
  • But my getters/setters are also exposed as data contracts. Wouldn't we lose the tracking code once it get serialized then deserialized? – CzarEclarinal Apr 08 '14 at 23:11
  • I made the tracking fields private variables for simplicity but you have of course to serialize and deserialize them, too. It just happens that my last exposure to WCF was some time ago and I can not provide a good working solution from the top of my head so I left out all the WCF specific pieces and just wanted to present the rough idea. How to best serialize tracking fields, tracking properties or a tracking dictionary you will have to figure out on your own. – Daniel Brückner Apr 09 '14 at 00:23
0

I ended up creating custom classes instead:

[DataContract, XmlRoot("Person")]
public class Person: BaseEntity
{
    [DataMember, XmlElement]
    public DomainString Prefix { get; set; }
    [DataMember, XmlElement]
    public DomainString FirstName { get; set; }
    [DataMember, XmlElement]
    public DomainString MiddleName { get; set; }
    [DataMember, XmlElement]
    public DomainString LastName { get; set; }
    [DataMember, XmlElement]
    public DomainString MaidenName { get; set; }
}

public class DomainString{
    public string Value {get; set;}
    public bool IsNull {get; set;}
}

Therefore in my wcf client, I can perform the ff. differentation:

if person.LastName == null, then the lastname was not set. if person.LastName.IsNull , then the lastname was set to null.