2

So what I'm basically doing is parsing a message (HL7 standard).

Sometimes these HL7 messages contain a "whole" record, with all the information, sometimes there is just the updated parts in it.

Here's an example of a row of data. Lets say this row contains some patient/client information like name, date of birth, etc. It could look like this:

|Mike|Miller|19790530|truck driver|blonde|m|

with the columns representing actually this:

|first name|surname|date of birth|job|hair color|gender|

Now this is a whole row of data.

An update might look like this (he married, lost his job and changed his hair color):

||O'Connor||""|brown||

where "" represents the value of the job column and brown represents the change of his hair color.

In the HL7 standard it's stated that omitting fields (like first name or gender, for instance) means that no change has been made, where as the "" means that the data in this field has been deleted. Fields with values might need an update. So my update logic for first name would look similar to this (pidEntity is a database object, not created code first, but database first and pidEntity.FirstName is a property)

var pid = this.message.PID; // patient identification object from parsed message
if (pid.PatientName.GivenName.Value == string.Empty)
{
    // "" => deletion flag
    pidEntity.FirstName = null;
}
else if (pid.PatientName.GivenName.Value == null)
{
    // omitted, no changes
    return;
}
pidEntity.FirstName = pid.PatientName.GivenName.Value;

I do a lot of string updates like this, so I thought hey - why not try with an extension method or method with ref parameter.

My first try was this:

// doesn't work because strings are immutable
public static void Update(this string @this, string newValue)
{
    if (newValue == string.Empty) @this = null;
    else if (newValue == null) return;
    @this = newValue;
}

// usage
pidEntity.FirstName.Update(pid.PatientName.GivenName.Value);

Changing the first parameter to this ref string @this does not work either. Neither does an update function with out or ref because properties can't be passed as a ref or out argument like this:

public static void Update(ref string property, string newValue)
// usage
Update(pidEntity.FirstName, pid.PatientName.GivenName.Value);

The most "elegant" I could come up with so far was either this, ignoring the fact that "" means set the database object's value to null and set it to an empty string instead.

pidEntity.FirstName = pid.PatientName.GivenName.Value ?? pidEntity.FirstName;

My other solution was an extension method working like this:

public static void UpdateString(this string hl7Value, Action<string> updateAct)
{
    if (updateAct == null) throw new ArgumentNullException(nameof(updateAct));

    if (hl7Value == string.Empty) updateAct(null);
    else if (hl7Value == null) return;
    updateAct(hl7Value);
}
// usage
pid.PatientName.GivenName.Value.UpdateString(v => pidEntity.FirstName = v);

I think there must be an easier way, but I need your help (maybe Reflection?) :)

Michael Schnerring
  • 3,584
  • 4
  • 23
  • 53
  • Good question. Since it essentially boils down to "how can I pass a property as a ref parameter" (I cannot see another solution to your problem), I have taken the liberty to mark your question as a duplicate of another question, which explains all the workarounds currently known. If you disagree, just tell me, and I'll reopen it. – Heinzi Jun 14 '16 at 15:27
  • I agree with you, that's a very nice answer - exactly what I was looking for. I wonder how I never found that on Google. As I suspected there's also a way with reflection and my personal favorite is the one with the expression. – Michael Schnerring Jun 14 '16 at 15:49

1 Answers1

1

Strings are immutable - you can create a new string, but you cannot update an existing instance of a string.

Jamiec
  • 133,658
  • 13
  • 134
  • 193