1

Consider below class being updated in database

public class ProductionLineItem
{
    public int Id { get; set; }
    public DateTime ProductionDate { get; set; }
    public string HandledBy { get; set; }
    public DateTime DateToMarket { get; set; }
}

void UpdateProductionRecord(ProductionLineItem existingRecord, ProductionLineItem modifiedRecord)
{
    existingRecord.Id = modifiedRecord.Id;
    existingRecord.ProductionDate = modifiedRecord.ProductionDate;
    existingRecord.HandledBy = modifiedRecord.HandledBy;
    existingRecord.DateToMarket = modifiedRecord.DateToMarket;
}

Customer wants to keep a log of all changed properties in dedicated table. I should be doing something like this:

void UpdateProductionRecordWithLog(ProductionLineItem existingRecord, ProductionLineItem modifiedRecord)
    {
        existingRecord.Id = modifiedRecord.Id;
        if (existingRecord.ProductionDate != modifiedRecord.ProductionDate)
        {
            existingRecord.ProductionDate = modifiedRecord.ProductionDate;
            //Log: productionDate update form xyz to abc
        }
        if (existingRecord.HandledBy != modifiedRecord.HandledBy)
        {
            existingRecord.HandledBy = modifiedRecord.HandledBy;
            //Log: HandledBy updated from Mr. John to Mr. Smith
        }
        if (existingRecord.DateToMarket != modifiedRecord.DateToMarket)
        {
            existingRecord.DateToMarket = modifiedRecord.DateToMarket;
            //Log: DateToMarket updated form 2013 to 2014
        }
    }

For small number of properties it should be fine, but if properties goes beyond 15-20. I believe this would not be best way to do it.

Can I make my code more clean? I am open to use any framework like AutoMapper or so, If needed.

Abhijeet
  • 13,562
  • 26
  • 94
  • 175

3 Answers3

2

There are multiple elegant solutions to your problem, some of those include:

  • You could use Aspect Oriented Programming (AOP, for frameworks see this answer) to capture every modification to a property. You could save those changes for later retrival or invoke events which are then logged.
  • You could put Reflection (e.g. PropertyInfo) to good use here and iterate over all properties and compare the current value. This will spare you from writing all properties by hand.
  • Reflection and Attributes in conjunction with the Properties which are needed to be logged will work too. Using Attributes as a kind of post-it note on those properties which are important to be logged.

Be aware that Reflection might impose some performance penalities.

Community
  • 1
  • 1
tobsen
  • 5,328
  • 3
  • 34
  • 51
0

Do you use Entity Framework? It supports INotifypropertychanged, which could be used:

How to raise an event on Property Change?

If not, your classes could implement INotifyPropertyChanged() themselves - while not great (you have to write geteers / setters explicitly), it provides a better decoupling than invoking a loggin facility in the Properties directly (what if, if your logging is not available).

I would be worried about performance issues, so I might store logs and only write once in a while...

Community
  • 1
  • 1
Christian Sauer
  • 10,351
  • 10
  • 53
  • 85
0

Well first you've done more than the requirement, in that you are only changing Existing item's properties if they are different.

Adding some new method to your class e.g. LogDifferences(ProductLineItem old, ProductLineItem new) and calling it from UpdateProductionItem would be good.

Personally I'd being going back to the Customer and saying what are you really trying to do and why, what they asked for smacks more of solution than requirement.

E.g. just log old record new record, like a DB transaction log. Do the an analysis of what changed when it's required.

One last possiblilty, that admittedly might cause more problems than it solves, is storing the values of the properties in say a Dictionary<String,dynamic> instead of discrete members.

Then logging changes based on Existing["ChangedToMarket"] = Modified["ChangedToMarket"] is fairly trival.

Tony Hopkinson
  • 20,172
  • 3
  • 31
  • 39