My biggest hack ever

Read this blog entry to know the background of this hack.

Every time the SqlXmlAdapter.Update method is used, you need to make sure that the values for the LIKE clauses of the text columns are escaped. This means every occurrence of [ needs to be replaced with [[]. And here’s the catch: it’s the original value of the DataRow that needs to be altered. You think: “Easy peasy”? Well, here we go:

row[columnToChange, DataRowVersion.Original] =
    Regex.Replace(originalValue, @”[“, “[[]”);

Stop right there, because this particular indexer of the DataRow is read-only. So I thought about working my way around it. It tried the following:

  • Take the modified row (of which I have little to know details other than the ones through regular DataRow properties), store current value of desired column, change the current value to escaped version of original value, call DataRow.AcceptChanges(), then setting the current value again. This failed because now the other values are accepted as well. The optimistic lock will always filter out any updates and deletes, unless the only columns updated need to be escaped.
  • Escape values before doing an actual update or delete. This only needs to be done before an update or delete, not on regular retrievals for display e.g.. This means it cannot be done inside the data layer’s retrieve method, because here we don’t know whether the data will be displayed or modified. In turn this lead to too many “fix” code, instead of just the Save method of my generic data layer.
  • Other stuff that didn’t work

That’s when I did my worst hack ever:
I used reflection to change the original value of a DataRow directly.

Ouch. Side note: Remco (Divinity) is going to laugh his pants off over this. I once slagged him over suggesting a similar approach as a workaround.

And if you are interested, here’s the offending code that I used:

private void FixEscapeCharacter(DataRow row, string fieldName)
{
  Regex expression =
new Regex(@”[“);
  string originalValue = (string)row[fieldName,
      DataRowVersion.Original];
  DataRowState rowState = row.RowState;

  if (expression.Match(originalValue).Success)
  {
   
// HACK: This is such a dirty hack. Since we cannot modify
    // original value
we go in using reflection and set it anyway. LOL

    Type rowType = typeof(DataRow);

    // Get record number for original version
    MethodInfo method = rowType.GetMethod(“GetRecordFromVersion”,
        BindingFlags.Instance | BindingFlags.NonPublic |
        BindingFlags.Public | BindingFlags.FlattenHierarchy,
        null, new Type[] { typeof(DataRowVersion) }, null);
    int record = (int)method.Invoke(row,
       
new object
[] { DataRowVersion.Original });

    // Change original value of column to fix
    DataColumn column = row.Table.Columns[fieldName];
    Type columnType = column.GetType();
    PropertyInfo property = columnType.GetProperty(“Item”,
        BindingFlags.Instance | BindingFlags.NonPublic,
null,
       
typeof
(Object), new Type[] { typeof(int) }, null);

    property.SetValue(column, expression.Replace(originalValue,
        “[[]”),
new object[] { record });
  }
}

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s