ASP.NET CORE 2.0 Hosting – Typesafe .Net Object Comparison using ZCompare

ZCompare is a powerful autonomous typesafe .NET object comparison tool. The modified data scenario where changes have been made to the original data is a common problem and essentially, as developers, we want to know what has beed added, deleted or modified. I am going to show how easy ZCompare can make detecting these changes and working with the ‘before’ and ‘after’ conditions of each item of data.

I have my original data from the database, and my user has made many changes to this data which reflects in my complex .NET object. I want to know if they have made changes to data or created new data, or deleted data. More importantly, I want to know what exactly has changed and what it has changed from. Sounds familiar?

Let’s assume we have a large object graph; a list of Suppliers for example. See here for class definitions. Let’s assume that originalSuppliers is a list of current suppliers from the database. We are creating them here on the fly for simplicity, using a helper class ‘SampleData’.I am using sample data from the Zaybu.Compare.Data assembly which is included in the ZCee Project.

‘results’ is a container for all the results. We will use this object to query for the results you want to work with.

Let’s get only those suppliers that have changes made to them. We use the results.GetResults<T>() method.

Note how each result has a ‘Status’ flag indicating if the Supplier has been added, deleted, or modified. Also, each result has an ‘OriginalValue’ and a ‘ChangedToValue’ property which reference the original object before changes and the modified object respectively.

So, perhaps if we were using a micro ORM…

Of course, things are rarely this simple. We have a Supplier object with a list of Products and a dictionary of Addresses as properties. These properties may have changed and we want to work with them as ‘Products’ and ‘Address’ types.

So, let’s go again and recreate our data and modify it again a bit differently.

We have all the modified suppliers in supplierResults. We can now loop through each one and see if they all have changes to their products.

Note how we use the results.GetResults<Product>() method and pass in ‘Products’ property of each individual supplier to get the product results for each supplier.

The GetSummary() method on each result is useful for verbosely showing changes in a user readable form.

Notice how we are only getting the results for ‘Products’ and not for ‘Addresses’.

We have another method to get results.

The GetResultsDeep() method takes a reference object and will get all the changes in the object tree from the supplied reference object (originalSuppliers in this case) and for the type.

Here we have all product changes for all suppliers.

This shows that with a combination of GetResults<T>(), GetResultsDeep<T>(), and the reference object passed into these methods, we can work with our results at any level of the object tree we wish.

Below are some brief examples of working with different types including a Dictionary and a struct.

Hopefully, the power of the GetResults<T>() and GetResultsDeep<T>() methods is now clear. Combined with the ‘OriginalValue’, ‘ChangedToValue’, and the ‘Status’ flag properties of results, they form the core of ZCompare functionality.

I hope, this has shown how you can work with your comparison results in a selective and targetted way. Using the reference object passed into these methods provides a context which allows manageable results from what can be an overwhelming result set. There is much more to ZCompare, such as the ability to Ignore properties, types, and namespaces, as well as custom comparitors, and key fields.