Pages

Wednesday 6 October 2010

Auditing entity changes in Silverlight 4

Well after some time searching around google to find details of how to audit changes made to my entities sets within Silverlight 4. I found myself going down various paths. Most of the examples show how to track these back at the server. However if you do not switch on ConcurrencyMode to Fixed within each entity field then you cannot compare the original values as these are reported as null. If you switch on the ConcurrencyMode then when the data is saved you will have a massive WHERE clause on updates [SQL profile and you will see].

However within the Silverlight client the original values were present, thus I wanted to try and compare these values on a save and then make the various audit changes. First draft of the code, simply wire up your SubmittingChanges event and use the code below. Comments welcome, as I'm sure there is a much better way of doing this.

void DataSource_SubmittingChanges(object sender, SubmittingChangesEventArgs e)

{
DataSource.SubmittingChanges -= DataSource_SubmittingChanges;
var changes = e.ChangeSet.ModifiedEntities;


foreach (var change in changes)
{

system_AUDIT audit = trackModifications(change);
// check if we have any audit detail
if (audit.system_AUDITDETAIL.Count != 0)
{
//add the audits
(DataSource.DomainContext as AppDomainContext).system_AUDITs.Add(audit);
}
}
}






public system_AUDIT trackModifications(System.ServiceModel.DomainServices.Client.Entity modifiedentity)
{
//get the entity name
var entityname = modifiedentity.GetType().Name.ToString();


//get the entity key [in this case its always the field rowguid]
System.Guid objectid = (System.Guid)modifiedentity.GetType().GetProperty("rowguid").GetValue(modifiedentity, null);


//get the original values
var originalentity = modifiedentity.GetOriginal();


// make sure we only bring back the properties defined for the entity
var properties = modifiedentity.GetType().GetProperties().Where(o => o.DeclaringType.Name == entityname);

//create a new audit guid
System.Guid g = System.Guid.NewGuid();


//setup the audit header
system_AUDIT audit = new system_AUDIT()
{
datecreated = DateTime.Now,
rowguid = g,
tablename = entityname,
objectid = objectid
};


//loop each property
foreach (System.Reflection.PropertyInfo property in properties)
{
var oldvalue = property.GetValue(originalentity, null);
var newvalue = property.GetValue(modifiedentity, null);

//if its a relationship should bring back null
if (oldvalue != null)
{
//normal property so compare the old and new values
if (oldvalue.ToString() != newvalue.ToString())
{
//change made so setup the audit detail
system_AUDITDETAIL detail = new system_AUDITDETAIL()
{
rowguid = System.Guid.NewGuid(),
fieldname = property.Name,
originalvalue = oldvalue.ToString(),
newvalue = newvalue.ToString(),
auditguid = g,
};
//add the detail to the audit heade record
audit.system_AUDITDETAIL.Add(detail);
}
}
}
//return the audit entity
return audit;
}